diff --git a/schemas/WebViewOptions.json b/schemas/WebViewOptions.json index bde6df9..f8811d7 100644 --- a/schemas/WebViewOptions.json +++ b/schemas/WebViewOptions.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "title": "WebViewOptions", + "title": "Options", "description": "Options for creating a webview.", "type": "object", "required": [ @@ -59,7 +59,7 @@ "description": "The content to load into the webview.", "anyOf": [ { - "$ref": "#/definitions/WebViewContent" + "$ref": "#/definitions/Content" }, { "type": "null" @@ -96,26 +96,7 @@ } }, "definitions": { - "Size": { - "type": "object", - "required": [ - "height", - "width" - ], - "properties": { - "height": { - "description": "The height of the window in logical pixels.", - "type": "number", - "format": "double" - }, - "width": { - "description": "The width of the window in logical pixels.", - "type": "number", - "format": "double" - } - } - }, - "WebViewContent": { + "Content": { "description": "The content to load into the webview.", "anyOf": [ { @@ -159,6 +140,25 @@ } ] }, + "Size": { + "type": "object", + "required": [ + "height", + "width" + ], + "properties": { + "height": { + "description": "The height of the window in logical pixels.", + "type": "number", + "format": "double" + }, + "width": { + "description": "The width of the window in logical pixels.", + "type": "number", + "format": "double" + } + } + }, "WindowSize": { "anyOf": [ { diff --git a/scripts/generate-schema/index.ts b/scripts/generate-schema/index.ts index 28a8381..b0a2b97 100644 --- a/scripts/generate-schema/index.ts +++ b/scripts/generate-schema/index.ts @@ -56,7 +56,7 @@ async function main() { if (!language || language === "typescript") { const tsContent = generateTypeScript( doc, - name, + doc.title, relativePath, ); const tsFilePath = join(tsSchemaDir, `${name}.ts`); diff --git a/src/bin/generate_schemas.rs b/src/bin/generate_schemas.rs index dff1232..12ba555 100644 --- a/src/bin/generate_schemas.rs +++ b/src/bin/generate_schemas.rs @@ -1,11 +1,11 @@ use schemars::schema_for; use std::fs::File; use std::io::Write; -use webview::{Message, Request, Response, WebViewOptions}; +use webview::{Message, Options, Request, Response}; fn main() { let schemas = [ - ("WebViewOptions", schema_for!(WebViewOptions)), + ("WebViewOptions", schema_for!(Options)), ("WebViewMessage", schema_for!(Message)), ("WebViewRequest", schema_for!(Request)), ("WebViewResponse", schema_for!(Response)), diff --git a/src/bin/webview.rs b/src/bin/webview.rs index 347f95d..de97e02 100644 --- a/src/bin/webview.rs +++ b/src/bin/webview.rs @@ -1,6 +1,6 @@ use std::env; use tracing::error; -use webview::{run, WebViewOptions}; +use webview::{run, Options}; fn main() { let subscriber = tracing_subscriber::fmt() @@ -11,7 +11,7 @@ fn main() { let args: Vec = env::args().collect(); - let webview_options: WebViewOptions = match serde_json::from_str(&args[1]) { + let webview_options: Options = match serde_json::from_str(&args[1]) { Ok(options) => options, Err(e) => { error!("Failed to parse webview options: {:?}", e); diff --git a/src/clients/deno/main.ts b/src/clients/deno/main.ts index 11c24d0..127de2b 100644 --- a/src/clients/deno/main.ts +++ b/src/clients/deno/main.ts @@ -23,10 +23,10 @@ */ import { EventEmitter } from "node:events"; -import { WebViewMessage } from "./schemas/WebViewMessage.ts"; -import type { WebViewOptions } from "./schemas/WebViewOptions.ts"; -import type { WebViewRequest } from "./schemas/WebViewRequest.ts"; -import { WebViewResponse } from "./schemas/WebViewResponse.ts"; +import { Message } from "./schemas/WebViewMessage.ts"; +import type { Options } from "./schemas/WebViewOptions.ts"; +import type { Request as WebViewRequest } from "./schemas/WebViewRequest.ts"; +import { Response as WebViewResponse } from "./schemas/WebViewResponse.ts"; import { monotonicUlid as ulid } from "jsr:@std/ulid"; import type { Except, Simplify } from "npm:type-fest"; import { join } from "jsr:@std/path"; @@ -50,14 +50,14 @@ if ( FmtSubscriber.setGlobalDefault({ level, color: true }); } -export type { WebViewOptions } from "./schemas/WebViewOptions.ts"; +export type { Options } from "./schemas/WebViewOptions.ts"; // Should match the cargo package version /** The version of the webview binary that's expected */ export const BIN_VERSION = "0.1.14"; type WebViewNotification = Extract< - WebViewMessage, + Message, { $type: "notification" } >["data"]; @@ -102,7 +102,7 @@ const returnAck = (result: WebViewResponse) => { }); }; -async function getWebViewBin(options: WebViewOptions) { +async function getWebViewBin(options: Options) { if ( Deno.permissions.querySync({ name: "env", variable: "WEBVIEW_BIN" }) .state === "granted" @@ -177,7 +177,7 @@ function getCacheDir(): string { * * Will automatically fetch the webview binary if it's not already downloaded */ -export async function createWebView(options: WebViewOptions): Promise { +export async function createWebView(options: Options): Promise { const binPath = await getWebViewBin(options); return new WebView(options, binPath); } @@ -197,7 +197,7 @@ export class WebView implements Disposable { #internalEvent = new EventEmitter(); #externalEvent = new EventEmitter(); #messageLoop: Promise; - #options: WebViewOptions; + #options: Options; /** * Creates a new webview window. @@ -205,7 +205,7 @@ export class WebView implements Disposable { * @param options - The options for the webview. * @param webviewBinaryPath - The path to the webview binary. */ - constructor(options: WebViewOptions, webviewBinaryPath: string) { + constructor(options: Options, webviewBinaryPath: string) { this.#options = options; this.#process = new Deno.Command(webviewBinaryPath, { args: [JSON.stringify(options)], @@ -252,7 +252,7 @@ export class WebView implements Disposable { continue; } trace("buffer", { buffer: this.#buffer }); - const result = WebViewMessage.safeParse( + const result = Message.safeParse( JSON.parse(this.#buffer.slice(0, newlineIndex)), ); this.#buffer = this.#buffer.slice(newlineIndex + 1); diff --git a/src/clients/deno/schemas/WebViewMessage.ts b/src/clients/deno/schemas/WebViewMessage.ts index 720ccae..b7ada2f 100644 --- a/src/clients/deno/schemas/WebViewMessage.ts +++ b/src/clients/deno/schemas/WebViewMessage.ts @@ -80,7 +80,7 @@ export type Response = /** * Complete definition of all outbound messages from the webview to the client. */ -export type WebViewMessage = +export type Message = | { $type: "notification"; @@ -120,10 +120,7 @@ export const Response: z.ZodType = z.discriminatedUnion("$type", [ z.object({ $type: z.literal("err"), id: z.string(), message: z.string() }), ]); -export const WebViewMessage: z.ZodType = z.discriminatedUnion( - "$type", - [ - z.object({ $type: z.literal("notification"), data: Notification }), - z.object({ $type: z.literal("response"), data: Response }), - ], -); +export const Message: z.ZodType = z.discriminatedUnion("$type", [ + z.object({ $type: z.literal("notification"), data: Notification }), + z.object({ $type: z.literal("response"), data: Response }), +]); diff --git a/src/clients/deno/schemas/WebViewOptions.ts b/src/clients/deno/schemas/WebViewOptions.ts index 4311b1e..cd99c41 100644 --- a/src/clients/deno/schemas/WebViewOptions.ts +++ b/src/clients/deno/schemas/WebViewOptions.ts @@ -1,17 +1,10 @@ // DO NOT EDIT: This file is auto-generated by generate-schema/index.ts import { z } from "npm:zod"; -export type Size = { - /** The height of the window in logical pixels. */ - height: number; - /** The width of the window in logical pixels. */ - width: number; -}; - /** * The content to load into the webview. */ -export type WebViewContent = +export type Content = | { /** Optional headers to send with the request. */ headers?: Record; @@ -25,13 +18,20 @@ export type WebViewContent = origin?: string; }; +export type Size = { + /** The height of the window in logical pixels. */ + height: number; + /** The width of the window in logical pixels. */ + width: number; +}; + export type WindowSizeStates = "maximized" | "fullscreen"; export type WindowSize = WindowSizeStates | Size; /** * Options for creating a webview. */ -export type WebViewOptions = { +export type Options = { /** Sets whether clicking an inactive window also clicks through to the webview. Default is false. */ acceptFirstMouse?: boolean; /** When true, all media can be played without user interaction. Default is false. */ @@ -63,7 +63,7 @@ export type WebViewOptions = { /** Sets whether host should be able to receive messages from the webview via `window.ipc.postMessage`. */ ipc?: boolean; /** The content to load into the webview. */ - load?: WebViewContent; + load?: Content; /** The size of the window. */ size?: WindowSize; /** Sets the title of the window. */ @@ -74,12 +74,7 @@ export type WebViewOptions = { userAgent?: string; }; -export const Size: z.ZodType = z.object({ - height: z.number(), - width: z.number(), -}); - -export const WebViewContent: z.ZodType = z.union([ +export const Content: z.ZodType = z.union([ z.object({ headers: z.record(z.string(), z.string()).optional(), url: z.string(), @@ -87,6 +82,11 @@ export const WebViewContent: z.ZodType = z.union([ z.object({ html: z.string(), origin: z.string() }), ]); +export const Size: z.ZodType = z.object({ + height: z.number(), + width: z.number(), +}); + export const WindowSizeStates: z.ZodType = z.enum([ "maximized", "fullscreen", @@ -96,7 +96,7 @@ export const WindowSize: z.ZodType = z.union([ Size, ]); -export const WebViewOptions: z.ZodType = z.object({ +export const Options: z.ZodType = z.object({ acceptFirstMouse: z.boolean().optional(), autoplay: z.boolean().optional(), clipboard: z.boolean().optional(), @@ -106,7 +106,7 @@ export const WebViewOptions: z.ZodType = z.object({ incognito: z.boolean().optional(), initializationScript: z.string(), ipc: z.boolean().optional(), - load: WebViewContent.optional(), + load: Content.optional(), size: WindowSize.optional(), title: z.string(), transparent: z.boolean().optional(), diff --git a/src/clients/deno/schemas/WebViewRequest.ts b/src/clients/deno/schemas/WebViewRequest.ts index 6a05e39..3b1fea8 100644 --- a/src/clients/deno/schemas/WebViewRequest.ts +++ b/src/clients/deno/schemas/WebViewRequest.ts @@ -11,7 +11,7 @@ export type Size = { /** * Explicit requests from the client to the webview. */ -export type WebViewRequest = +export type Request = | { $type: "getVersion"; /** The id of the request. */ @@ -112,56 +112,49 @@ export const Size: z.ZodType = z.object({ width: z.number(), }); -export const WebViewRequest: z.ZodType = z.discriminatedUnion( - "$type", - [ - z.object({ $type: z.literal("getVersion"), id: z.string() }), - z.object({ $type: z.literal("eval"), id: z.string(), js: z.string() }), - z.object({ - $type: z.literal("setTitle"), - id: z.string(), - title: z.string(), - }), - z.object({ $type: z.literal("getTitle"), id: z.string() }), - z.object({ - $type: z.literal("setVisibility"), - id: z.string(), - visible: z.boolean(), - }), - z.object({ $type: z.literal("isVisible"), id: z.string() }), - z.object({ $type: z.literal("openDevTools"), id: z.string() }), - z.object({ - $type: z.literal("getSize"), - id: z.string(), - include_decorations: z.boolean().optional(), - }), - z.object({ $type: z.literal("setSize"), id: z.string(), size: Size }), - z.object({ - $type: z.literal("fullscreen"), - fullscreen: z.boolean().optional(), - id: z.string(), - }), - z.object({ - $type: z.literal("maximize"), - id: z.string(), - maximized: z.boolean().optional(), - }), - z.object({ - $type: z.literal("minimize"), - id: z.string(), - minimized: z.boolean().optional(), - }), - z.object({ - $type: z.literal("loadHtml"), - html: z.string(), - id: z.string(), - origin: z.string().optional(), - }), - z.object({ - $type: z.literal("loadUrl"), - headers: z.record(z.string(), z.string()).optional(), - id: z.string(), - url: z.string(), - }), - ], -); +export const Request: z.ZodType = z.discriminatedUnion("$type", [ + z.object({ $type: z.literal("getVersion"), id: z.string() }), + z.object({ $type: z.literal("eval"), id: z.string(), js: z.string() }), + z.object({ $type: z.literal("setTitle"), id: z.string(), title: z.string() }), + z.object({ $type: z.literal("getTitle"), id: z.string() }), + z.object({ + $type: z.literal("setVisibility"), + id: z.string(), + visible: z.boolean(), + }), + z.object({ $type: z.literal("isVisible"), id: z.string() }), + z.object({ $type: z.literal("openDevTools"), id: z.string() }), + z.object({ + $type: z.literal("getSize"), + id: z.string(), + include_decorations: z.boolean().optional(), + }), + z.object({ $type: z.literal("setSize"), id: z.string(), size: Size }), + z.object({ + $type: z.literal("fullscreen"), + fullscreen: z.boolean().optional(), + id: z.string(), + }), + z.object({ + $type: z.literal("maximize"), + id: z.string(), + maximized: z.boolean().optional(), + }), + z.object({ + $type: z.literal("minimize"), + id: z.string(), + minimized: z.boolean().optional(), + }), + z.object({ + $type: z.literal("loadHtml"), + html: z.string(), + id: z.string(), + origin: z.string().optional(), + }), + z.object({ + $type: z.literal("loadUrl"), + headers: z.record(z.string(), z.string()).optional(), + id: z.string(), + url: z.string(), + }), +]); diff --git a/src/clients/deno/schemas/WebViewResponse.ts b/src/clients/deno/schemas/WebViewResponse.ts index e23f43f..b1ecc8d 100644 --- a/src/clients/deno/schemas/WebViewResponse.ts +++ b/src/clients/deno/schemas/WebViewResponse.ts @@ -38,7 +38,7 @@ export type ResultType = /** * Responses from the webview to the client. */ -export type WebViewResponse = +export type Response = | { $type: "ack"; @@ -72,15 +72,8 @@ export const ResultType: z.ZodType = z.discriminatedUnion("$type", [ z.object({ $type: z.literal("size"), value: SizeWithScale }), ]); -export const WebViewResponse: z.ZodType = z.discriminatedUnion( - "$type", - [ - z.object({ $type: z.literal("ack"), id: z.string() }), - z.object({ - $type: z.literal("result"), - id: z.string(), - result: ResultType, - }), - z.object({ $type: z.literal("err"), id: z.string(), message: z.string() }), - ], -); +export const Response: z.ZodType = z.discriminatedUnion("$type", [ + z.object({ $type: z.literal("ack"), id: z.string() }), + z.object({ $type: z.literal("result"), id: z.string(), result: ResultType }), + z.object({ $type: z.literal("err"), id: z.string(), message: z.string() }), +]); diff --git a/src/lib.rs b/src/lib.rs index 0a105c1..79951ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,12 +67,12 @@ pub enum WindowSize { /// Options for creating a webview. #[derive(JsonSchema, Deserialize, Debug)] #[serde(rename_all = "camelCase")] -pub struct WebViewOptions { +pub struct Options { /// Sets the title of the window. title: String, /// The content to load into the webview. #[serde(default)] - load: Option, + load: Option, /// The size of the window. #[serde(default)] size: Option, @@ -126,7 +126,7 @@ fn default_true() -> bool { #[derive(JsonSchema, Deserialize, Debug)] #[serde(rename_all = "camelCase")] #[serde(untagged)] -pub enum WebViewContent { +pub enum Content { Url { /// Url to load in the webview. Note: Don't use data URLs here, as they are not supported. Use the `html` field instead. url: String, @@ -409,7 +409,7 @@ fn process_output( }); } -pub fn run(webview_options: WebViewOptions) -> wry::Result<()> { +pub fn run(webview_options: Options) -> wry::Result<()> { info!("Starting webview with options: {:?}", webview_options); // These two mutexes are used to store the html and origin if the webview is created with html. @@ -443,7 +443,7 @@ pub fn run(webview_options: WebViewOptions) -> wry::Result<()> { let html_mutex_init = html_mutex.clone(); let mut webview_builder = match webview_options.load { - Some(WebViewContent::Url { url, headers }) => { + Some(Content::Url { url, headers }) => { let mut webview_builder = WebViewBuilder::new().with_url(url); if let Some(headers) = headers { let headers = headers @@ -459,7 +459,7 @@ pub fn run(webview_options: WebViewOptions) -> wry::Result<()> { } webview_builder } - Some(WebViewContent::Html { html, origin }) => { + Some(Content::Html { html, origin }) => { origin_mutex.lock().clone_from(&origin); *html_mutex.lock() = html; WebViewBuilder::new().with_url(format!("load-html://{}", origin))