@ishibashi0112/webview2-bridge-client 0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ishibashi0112
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @ishibashi0112/webview2-bridge-client
2
+
3
+ Front-end runtime for [webview2-bridge](https://github.com/ishibashi0112/webview2-bridge): a typed JSON-RPC 2.0 client that
4
+ talks to a VB.NET WinForms host through WebView2 `postMessage`, validated on both ends with the zod contract you wrote for
5
+ [`@ishibashi0112/webview2-bridge-gen`](https://www.npmjs.com/package/@ishibashi0112/webview2-bridge-gen).
6
+
7
+ ```sh
8
+ pnpm add @ishibashi0112/webview2-bridge-client zod
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { createClient, MemoryTransport, selectTransport } from "@ishibashi0112/webview2-bridge-client";
15
+ import { contract, type Contract } from "@webview2-bridge/contract"; // your zod contract
16
+ import { handlers } from "./mock/handlers"; // MemoryHandlers<Contract>
17
+
18
+ // WebView2 present → WebView2Transport; otherwise the mode from VITE_TRANSPORT (default "memory")
19
+ const { mode, transport } = selectTransport({
20
+ mode: import.meta.env.VITE_TRANSPORT,
21
+ factories: { memory: () => new MemoryTransport<Contract>(handlers, { delay: 100 }) },
22
+ });
23
+
24
+ export const client = createClient(contract, transport);
25
+
26
+ const res = await client.parts.search({ keyword: "M6" }); // typed: { items: Part[] }
27
+ const off = client.events.on("progress", (p) => console.log(p.percent)); // host → web notifications
28
+ ```
29
+
30
+ - **Input** is validated with zod before sending; **output** and **event payloads** after receiving.
31
+ Mismatches reject with `BridgeValidationError` (`direction`, `method`, `issues`).
32
+ - Host errors arrive as `BridgeError` with the JSON-RPC `code` / `message` / `data`
33
+ (`-32000` + exception type name for unhandled VB exceptions, or the code of a `JsonRpcException`).
34
+ - `BridgeTimeoutError` after `timeoutMs` (default 30 s); `BridgeDisposedError` when the transport was disposed.
35
+
36
+ ## Transports
37
+
38
+ | Transport | Use |
39
+ |---|---|
40
+ | `WebView2Transport` | inside the WinForms host (`window.chrome.webview`). Wire format: JSON-RPC 2.0 over `postMessage` / `PostWebMessageAsJson` |
41
+ | `MemoryTransport<C>(handlers, { delay })` | plain browser / tests. Handlers are typed from the contract: `{ parts: { search: async (input, { emit }) => output } }`; `emit("progress", payload)` simulates host events. Handler exceptions become `-32000` errors like on the VB side |
42
+ | your own | implement `Transport { call(method, params); on(method, handler) }` (e.g. msw / http) and add it to `selectTransport` factories |
43
+
44
+ Protocol details and the VB.NET side (`WebView2Bridge.Runtime`, `WebView2Bridge.WinForms` on NuGet) are documented in the repository.
45
+
46
+ MIT
@@ -0,0 +1,32 @@
1
+ import type { z } from "zod";
2
+ import { BridgeValidationError, type ContractShape, type Transport } from "./transport.js";
3
+ /** `client.parts.search(input)` の形。namespace → method → 型付き関数 */
4
+ export type ClientMethods<C extends ContractShape> = {
5
+ [NS in keyof C["methods"]]: {
6
+ [M in keyof C["methods"][NS]]: (input: z.input<C["methods"][NS][M]["input"]>) => Promise<z.output<C["methods"][NS][M]["output"]>>;
7
+ };
8
+ };
9
+ export interface ClientEvents<C extends ContractShape> {
10
+ /** イベントを購読する。戻り値は購読解除関数 */
11
+ on<E extends keyof C["events"] & string>(name: E, handler: (payload: z.output<C["events"][E]>) => void): () => void;
12
+ }
13
+ export type Client<C extends ContractShape> = ClientMethods<C> & {
14
+ events: ClientEvents<C>;
15
+ /** 生の transport(デバッグ・破棄用) */
16
+ transport: Transport;
17
+ };
18
+ export interface CreateClientOptions {
19
+ /**
20
+ * 受信したイベントが契約に合わなかったときの処理。
21
+ * 既定は console.error に出してハンドラを呼ばない。
22
+ */
23
+ onEventValidationError?: (error: BridgeValidationError) => void;
24
+ }
25
+ /**
26
+ * 契約と transport から型付きクライアントを作る。
27
+ * - 入力は送信前に zod で parse(失敗: BridgeValidationError, direction "input")
28
+ * - 出力は受信後に zod で parse(失敗: BridgeValidationError, direction "output")
29
+ * - イベントは受信後に zod で parse(失敗: onEventValidationError)
30
+ */
31
+ export declare function createClient<C extends ContractShape>(contract: C, transport: Transport, options?: CreateClientOptions): Client<C>;
32
+ //# sourceMappingURL=create-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../src/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EACL,qBAAqB,EAErB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAC;AAExB,iEAAiE;AACjE,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,aAAa,IAAI;KAClD,EAAE,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG;SACzB,CAAC,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAC7B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KACzC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;KACtD;CACF,CAAC;AAEF,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,aAAa;IACnD,2BAA2B;IAC3B,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EACrC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,GACnD,MAAM,IAAI,CAAC;CACf;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,aAAa,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IAC/D,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACxB,6BAA6B;IAC7B,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACjE;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAClD,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,mBAAwB,GAChC,MAAM,CAAC,CAAC,CAAC,CA+CX"}
@@ -0,0 +1,55 @@
1
+ import { BridgeValidationError, eventMethod, } from "./transport.js";
2
+ const RESERVED_NAMESPACES = new Set(["events", "transport"]);
3
+ /**
4
+ * 契約と transport から型付きクライアントを作る。
5
+ * - 入力は送信前に zod で parse(失敗: BridgeValidationError, direction "input")
6
+ * - 出力は受信後に zod で parse(失敗: BridgeValidationError, direction "output")
7
+ * - イベントは受信後に zod で parse(失敗: onEventValidationError)
8
+ */
9
+ export function createClient(contract, transport, options = {}) {
10
+ const client = {};
11
+ for (const [ns, methods] of Object.entries(contract.methods)) {
12
+ if (RESERVED_NAMESPACES.has(ns)) {
13
+ throw new Error(`Namespace "${ns}" is reserved on the client object`);
14
+ }
15
+ const nsObj = {};
16
+ for (const [name, def] of Object.entries(methods)) {
17
+ const rpc = `${ns}.${name}`;
18
+ nsObj[name] = async (input) => {
19
+ const parsedInput = def.input.safeParse(input);
20
+ if (!parsedInput.success)
21
+ throw new BridgeValidationError("input", rpc, parsedInput.error, input);
22
+ const raw = await transport.call(rpc, parsedInput.data);
23
+ const parsedOutput = def.output.safeParse(raw);
24
+ if (!parsedOutput.success)
25
+ throw new BridgeValidationError("output", rpc, parsedOutput.error, raw);
26
+ return parsedOutput.data;
27
+ };
28
+ }
29
+ client[ns] = nsObj;
30
+ }
31
+ const onEventValidationError = options.onEventValidationError ??
32
+ ((e) => {
33
+ console.error("[webview2-bridge]", e.message, e.issues);
34
+ });
35
+ const events = {
36
+ on(name, handler) {
37
+ const schema = contract.events[name];
38
+ if (!schema)
39
+ throw new Error(`Unknown event "${name}"`);
40
+ const rpc = eventMethod(name);
41
+ return transport.on(rpc, (raw) => {
42
+ const parsed = schema.safeParse(raw);
43
+ if (!parsed.success) {
44
+ onEventValidationError(new BridgeValidationError("event", rpc, parsed.error, raw));
45
+ return;
46
+ }
47
+ handler(parsed.data);
48
+ });
49
+ },
50
+ };
51
+ client["events"] = events;
52
+ client["transport"] = transport;
53
+ return client;
54
+ }
55
+ //# sourceMappingURL=create-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-client.js","sourceRoot":"","sources":["../src/create-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { BridgeDisposedError, BridgeError, BridgeTimeoutError, BridgeValidationError, EVENT_PREFIX, JsonRpcErrorCodes, eventMethod, isJsonRpcNotification, isJsonRpcResponse, type ContractShape, type JsonRpcErrorObject, type JsonRpcFailure, type JsonRpcId, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type JsonRpcSuccess, type MethodShape, type Transport, type ValidationDirection, } from "./transport.js";
2
+ export { WebView2Transport, getWebView2, type WebView2Like, type WebView2TransportOptions } from "./webview2.js";
3
+ export { MemoryTransport, type MemoryContext, type MemoryHandlers, type MemoryTransportOptions } from "./memory.js";
4
+ export { createClient, type Client, type ClientEvents, type ClientMethods, type CreateClientOptions } from "./create-client.js";
5
+ export { selectTransport, type SelectTransportOptions, type TransportFactory } from "./select-transport.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACjH,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAChI,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { BridgeDisposedError, BridgeError, BridgeTimeoutError, BridgeValidationError, EVENT_PREFIX, JsonRpcErrorCodes, eventMethod, isJsonRpcNotification, isJsonRpcResponse, } from "./transport.js";
2
+ export { WebView2Transport, getWebView2 } from "./webview2.js";
3
+ export { MemoryTransport } from "./memory.js";
4
+ export { createClient } from "./create-client.js";
5
+ export { selectTransport } from "./select-transport.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,GAYlB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAoD,MAAM,eAAe,CAAC;AACjH,OAAO,EAAE,eAAe,EAAwE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,YAAY,EAAgF,MAAM,oBAAoB,CAAC;AAChI,OAAO,EAAE,eAAe,EAAsD,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { z } from "zod";
2
+ import { type ContractShape, type Transport } from "./transport.js";
3
+ /** ハンドラから MemoryTransport 自身の機能(イベント発火)を使うためのコンテキスト */
4
+ export interface MemoryContext<C extends ContractShape> {
5
+ emit: <E extends keyof C["events"] & string>(name: E, payload: z.input<C["events"][E]>) => void;
6
+ }
7
+ /** 契約から型付けされたモックハンドラ。`{ parts: { search: async (input, ctx) => output } }` */
8
+ export type MemoryHandlers<C extends ContractShape> = {
9
+ [NS in keyof C["methods"]]: {
10
+ [M in keyof C["methods"][NS]]: (input: z.output<C["methods"][NS][M]["input"]>, ctx: MemoryContext<C>) => Promise<z.input<C["methods"][NS][M]["output"]>> | z.input<C["methods"][NS][M]["output"]>;
11
+ };
12
+ };
13
+ export interface MemoryTransportOptions {
14
+ /** 応答を遅らせる ms(ローディング表示の確認用) */
15
+ delay?: number;
16
+ }
17
+ /**
18
+ * ブラウザ単体で動かすための in-memory transport。
19
+ * 実際の通信と同じく、要求・応答・イベントは JSON に一度直列化して往復させる
20
+ * (undefined の欠落や Date の文字列化など、wire 上の挙動を再現する)。
21
+ */
22
+ export declare class MemoryTransport<C extends ContractShape> implements Transport {
23
+ private readonly handlers;
24
+ private readonly listeners;
25
+ private readonly delay;
26
+ private readonly context;
27
+ constructor(handlers: MemoryHandlers<C>, options?: MemoryTransportOptions);
28
+ call(method: string, params: unknown): Promise<unknown>;
29
+ on(method: string, handler: (params: unknown) => void): () => void;
30
+ /** Host → Web のイベントを擬似発火する */
31
+ emit<E extends keyof C["events"] & string>(name: E, payload: z.input<C["events"][E]>): void;
32
+ private lookup;
33
+ }
34
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAC;AAExB,uDAAuD;AACvD,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,aAAa;IACpD,IAAI,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CACjG;AAED,8EAA8E;AAC9E,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,aAAa,IAAI;KACnD,EAAE,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG;SACzB,CAAC,IAAI,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAC7C,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,KAClB,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;KAC9F;CACF,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,eAAe,CAAC,CAAC,SAAS,aAAa,CAAE,YAAW,SAAS;IAMtE,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;gBAGxB,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,EAC5C,OAAO,GAAE,sBAA2B;IAMhC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB7D,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAIlE,8BAA8B;IAC9B,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAI3F,OAAO,CAAC,MAAM;CASf"}
package/dist/memory.js ADDED
@@ -0,0 +1,62 @@
1
+ import { BridgeError, eventMethod, JsonRpcErrorCodes, ListenerMap, } from "./transport.js";
2
+ /**
3
+ * ブラウザ単体で動かすための in-memory transport。
4
+ * 実際の通信と同じく、要求・応答・イベントは JSON に一度直列化して往復させる
5
+ * (undefined の欠落や Date の文字列化など、wire 上の挙動を再現する)。
6
+ */
7
+ export class MemoryTransport {
8
+ handlers;
9
+ listeners = new ListenerMap();
10
+ delay;
11
+ context;
12
+ constructor(handlers, options = {}) {
13
+ this.handlers = handlers;
14
+ this.delay = options.delay ?? 0;
15
+ this.context = { emit: (name, payload) => this.emit(name, payload) };
16
+ }
17
+ async call(method, params) {
18
+ const handler = this.lookup(method);
19
+ if (!handler) {
20
+ throw new BridgeError({ code: JsonRpcErrorCodes.MethodNotFound, message: `Method not found: ${method}` }, method);
21
+ }
22
+ if (this.delay > 0)
23
+ await sleep(this.delay);
24
+ try {
25
+ const result = await handler(roundTrip(params), this.context);
26
+ return roundTrip(result);
27
+ }
28
+ catch (e) {
29
+ if (e instanceof BridgeError)
30
+ throw e;
31
+ // VB 側の未処理例外と同じ形(-32000, message, data = 例外型名)に揃える
32
+ const err = e instanceof Error ? e : new Error(String(e));
33
+ throw new BridgeError({ code: JsonRpcErrorCodes.ServerError, message: err.message, data: err.name }, method);
34
+ }
35
+ }
36
+ on(method, handler) {
37
+ return this.listeners.add(method, handler);
38
+ }
39
+ /** Host → Web のイベントを擬似発火する */
40
+ emit(name, payload) {
41
+ this.listeners.dispatch(eventMethod(name), roundTrip(payload));
42
+ }
43
+ lookup(method) {
44
+ const dot = method.indexOf(".");
45
+ if (dot < 0)
46
+ return undefined;
47
+ const ns = method.slice(0, dot);
48
+ const name = method.slice(dot + 1);
49
+ const nsHandlers = this.handlers[ns];
50
+ const h = nsHandlers?.[name];
51
+ return typeof h === "function" ? h : undefined;
52
+ }
53
+ }
54
+ function roundTrip(v) {
55
+ if (v === undefined)
56
+ return v;
57
+ return JSON.parse(JSON.stringify(v));
58
+ }
59
+ function sleep(ms) {
60
+ return new Promise((r) => setTimeout(r, ms));
61
+ }
62
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Transport } from "./transport.js";
2
+ export type TransportFactory = () => Transport;
3
+ export interface SelectTransportOptions {
4
+ /**
5
+ * 明示的なモード。アプリ側で `import.meta.env.VITE_TRANSPORT` を渡す想定。
6
+ * undefined / "" / "auto" のときは WebView2 があれば "webview2"、なければ fallback。
7
+ */
8
+ mode?: string | undefined;
9
+ /** モード名 → transport 生成。"webview2" を省略すると既定の WebView2Transport */
10
+ factories: Record<string, TransportFactory>;
11
+ /** auto で WebView2 が無いときに使うモード(既定 "memory") */
12
+ fallback?: string;
13
+ }
14
+ /**
15
+ * 実行環境から transport を選ぶ。
16
+ * 将来 "msw" / "http" などを足すときは factories にキーを追加するだけでよい。
17
+ */
18
+ export declare function selectTransport(options: SelectTransportOptions): {
19
+ mode: string;
20
+ transport: Transport;
21
+ };
22
+ //# sourceMappingURL=select-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-transport.d.ts","sourceRoot":"","sources":["../src/select-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC;AAE/C,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC5C,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,CAcvG"}
@@ -0,0 +1,21 @@
1
+ import { WebView2Transport } from "./webview2.js";
2
+ /**
3
+ * 実行環境から transport を選ぶ。
4
+ * 将来 "msw" / "http" などを足すときは factories にキーを追加するだけでよい。
5
+ */
6
+ export function selectTransport(options) {
7
+ const factories = {
8
+ webview2: () => new WebView2Transport(),
9
+ ...options.factories,
10
+ };
11
+ let mode = options.mode?.trim() || "auto";
12
+ if (mode === "auto") {
13
+ mode = WebView2Transport.isAvailable() ? "webview2" : (options.fallback ?? "memory");
14
+ }
15
+ const factory = factories[mode];
16
+ if (!factory) {
17
+ throw new Error(`Unknown transport mode "${mode}" (available: ${Object.keys(factories).join(", ")})`);
18
+ }
19
+ return { mode, transport: factory() };
20
+ }
21
+ //# sourceMappingURL=select-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-transport.js","sourceRoot":"","sources":["../src/select-transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAgBlD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAA+B;IAC7D,MAAM,SAAS,GAAqC;QAClD,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;QACvC,GAAG,OAAO,CAAC,SAAS;KACrB,CAAC;IACF,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC;IAC1C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,iBAAiB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,iBAAiB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxG,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { z } from "zod";
2
+ export interface MethodShape {
3
+ input: z.ZodType;
4
+ output: z.ZodType;
5
+ }
6
+ export interface ContractShape {
7
+ methods: Record<string, Record<string, MethodShape>>;
8
+ events: Record<string, z.ZodType>;
9
+ }
10
+ export type JsonRpcId = string | number;
11
+ export interface JsonRpcRequest {
12
+ jsonrpc: "2.0";
13
+ id: JsonRpcId;
14
+ method: string;
15
+ params?: unknown;
16
+ }
17
+ export interface JsonRpcErrorObject {
18
+ code: number;
19
+ message: string;
20
+ data?: unknown;
21
+ }
22
+ export interface JsonRpcSuccess {
23
+ jsonrpc: "2.0";
24
+ id: JsonRpcId | null;
25
+ result: unknown;
26
+ }
27
+ export interface JsonRpcFailure {
28
+ jsonrpc: "2.0";
29
+ id: JsonRpcId | null;
30
+ error: JsonRpcErrorObject;
31
+ }
32
+ export type JsonRpcResponse = JsonRpcSuccess | JsonRpcFailure;
33
+ /** Host → Web の通知(id なし)。イベントは method = "event.<name>" */
34
+ export interface JsonRpcNotification {
35
+ jsonrpc: "2.0";
36
+ method: string;
37
+ params?: unknown;
38
+ }
39
+ export declare const JsonRpcErrorCodes: {
40
+ readonly ParseError: -32700;
41
+ readonly InvalidRequest: -32600;
42
+ readonly MethodNotFound: -32601;
43
+ readonly InvalidParams: -32602;
44
+ readonly InternalError: -32603;
45
+ /** アプリ定義エラーの既定値。VB 側の未処理例外はこのコード */
46
+ readonly ServerError: -32000;
47
+ };
48
+ export declare const EVENT_PREFIX = "event.";
49
+ export declare function eventMethod(name: string): string;
50
+ export declare function isJsonRpcResponse(v: unknown): v is JsonRpcResponse;
51
+ export declare function isJsonRpcNotification(v: unknown): v is JsonRpcNotification;
52
+ /**
53
+ * 通信路の抽象。createClient はこれだけに依存する。
54
+ * - call: 要求/応答。失敗は BridgeError(または派生)で reject
55
+ * - on: 通知の購読。`method` は "event.progress" のような完全名。戻り値は購読解除関数
56
+ */
57
+ export interface Transport {
58
+ call(method: string, params: unknown): Promise<unknown>;
59
+ on(method: string, handler: (params: unknown) => void): () => void;
60
+ }
61
+ /** Host が JSON-RPC error を返した(または transport 層で同等の失敗が起きた) */
62
+ export declare class BridgeError extends Error {
63
+ readonly code: number;
64
+ readonly data: unknown;
65
+ readonly method: string | undefined;
66
+ constructor(error: JsonRpcErrorObject, method?: string);
67
+ }
68
+ /** 応答が timeoutMs 以内に返らなかった */
69
+ export declare class BridgeTimeoutError extends BridgeError {
70
+ constructor(method: string, timeoutMs: number);
71
+ }
72
+ /** transport が破棄された(ページ遷移など)ため応答を待てない */
73
+ export declare class BridgeDisposedError extends BridgeError {
74
+ constructor(method: string);
75
+ }
76
+ export type ValidationDirection = "input" | "output" | "event";
77
+ /** 送信前の入力、受信後の出力・イベントが zod 契約に合わない */
78
+ export declare class BridgeValidationError extends Error {
79
+ readonly direction: ValidationDirection;
80
+ readonly method: string;
81
+ readonly issues: z.core.$ZodIssue[];
82
+ readonly value: unknown;
83
+ constructor(direction: ValidationDirection, method: string, error: z.ZodError, value: unknown);
84
+ }
85
+ export declare class ListenerMap {
86
+ private readonly map;
87
+ add(method: string, handler: (params: unknown) => void): () => void;
88
+ dispatch(method: string, params: unknown): void;
89
+ clear(): void;
90
+ }
91
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ export const JsonRpcErrorCodes = {
2
+ ParseError: -32700,
3
+ InvalidRequest: -32600,
4
+ MethodNotFound: -32601,
5
+ InvalidParams: -32602,
6
+ InternalError: -32603,
7
+ /** アプリ定義エラーの既定値。VB 側の未処理例外はこのコード */
8
+ ServerError: -32000,
9
+ };
10
+ export const EVENT_PREFIX = "event.";
11
+ export function eventMethod(name) {
12
+ return `${EVENT_PREFIX}${name}`;
13
+ }
14
+ function isRecord(v) {
15
+ return typeof v === "object" && v !== null;
16
+ }
17
+ export function isJsonRpcResponse(v) {
18
+ return isRecord(v) && v["jsonrpc"] === "2.0" && "id" in v && ("result" in v || isRecord(v["error"]));
19
+ }
20
+ export function isJsonRpcNotification(v) {
21
+ return isRecord(v) && v["jsonrpc"] === "2.0" && !("id" in v) && typeof v["method"] === "string";
22
+ }
23
+ // ---------------------------------------------------------------- errors
24
+ /** Host が JSON-RPC error を返した(または transport 層で同等の失敗が起きた) */
25
+ export class BridgeError extends Error {
26
+ code;
27
+ data;
28
+ method;
29
+ constructor(error, method) {
30
+ super(error.message);
31
+ this.name = "BridgeError";
32
+ this.code = error.code;
33
+ this.data = error.data;
34
+ this.method = method;
35
+ }
36
+ }
37
+ /** 応答が timeoutMs 以内に返らなかった */
38
+ export class BridgeTimeoutError extends BridgeError {
39
+ constructor(method, timeoutMs) {
40
+ super({ code: JsonRpcErrorCodes.InternalError, message: `Timeout after ${timeoutMs}ms: ${method}` }, method);
41
+ this.name = "BridgeTimeoutError";
42
+ }
43
+ }
44
+ /** transport が破棄された(ページ遷移など)ため応答を待てない */
45
+ export class BridgeDisposedError extends BridgeError {
46
+ constructor(method) {
47
+ super({ code: JsonRpcErrorCodes.InternalError, message: `Transport disposed: ${method}` }, method);
48
+ this.name = "BridgeDisposedError";
49
+ }
50
+ }
51
+ /** 送信前の入力、受信後の出力・イベントが zod 契約に合わない */
52
+ export class BridgeValidationError extends Error {
53
+ direction;
54
+ method;
55
+ issues;
56
+ value;
57
+ constructor(direction, method, error, value) {
58
+ super(`${direction} validation failed for ${method}: ${error.message}`);
59
+ this.name = "BridgeValidationError";
60
+ this.direction = direction;
61
+ this.method = method;
62
+ this.issues = error.issues;
63
+ this.value = value;
64
+ }
65
+ }
66
+ // ---------------------------------------------------------------- listeners(transport 実装で共用)
67
+ export class ListenerMap {
68
+ map = new Map();
69
+ add(method, handler) {
70
+ let set = this.map.get(method);
71
+ if (!set) {
72
+ set = new Set();
73
+ this.map.set(method, set);
74
+ }
75
+ set.add(handler);
76
+ return () => {
77
+ set.delete(handler);
78
+ if (set.size === 0)
79
+ this.map.delete(method);
80
+ };
81
+ }
82
+ dispatch(method, params) {
83
+ const set = this.map.get(method);
84
+ if (!set)
85
+ return;
86
+ for (const h of [...set]) {
87
+ try {
88
+ h(params);
89
+ }
90
+ catch (e) {
91
+ // 1 つのハンドラの例外で他のハンドラや transport を止めない
92
+ console.error(`[webview2-bridge] listener for ${method} threw`, e);
93
+ }
94
+ }
95
+ }
96
+ clear() {
97
+ this.map.clear();
98
+ }
99
+ }
100
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAqDA,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,UAAU,EAAE,CAAC,KAAK;IAClB,cAAc,EAAE,CAAC,KAAK;IACtB,cAAc,EAAE,CAAC,KAAK;IACtB,aAAa,EAAE,CAAC,KAAK;IACrB,aAAa,EAAE,CAAC,KAAK;IACrB,oCAAoC;IACpC,WAAW,EAAE,CAAC,KAAK;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,GAAG,YAAY,GAAG,IAAI,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAU;IAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,CAAU;IAC9C,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;AAClG,CAAC;AAcD,0EAA0E;AAE1E,4DAA4D;AAC5D,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAS;IACb,IAAI,CAAU;IACd,MAAM,CAAqB;IAEpC,YAAY,KAAyB,EAAE,MAAe;QACpD,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,8BAA8B;AAC9B,MAAM,OAAO,kBAAmB,SAAQ,WAAW;IACjD,YAAY,MAAc,EAAE,SAAiB;QAC3C,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,aAAa,EAAE,OAAO,EAAE,iBAAiB,SAAS,OAAO,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7G,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,yCAAyC;AACzC,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IAClD,YAAY,MAAc;QACxB,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,aAAa,EAAE,OAAO,EAAE,uBAAuB,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACnG,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAID,sCAAsC;AACtC,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,SAAS,CAAsB;IAC/B,MAAM,CAAS;IACf,MAAM,CAAqB;IAC3B,KAAK,CAAU;IAExB,YAAY,SAA8B,EAAE,MAAc,EAAE,KAAiB,EAAE,KAAc;QAC3F,KAAK,CAAC,GAAG,SAAS,0BAA0B,MAAM,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,8FAA8F;AAE9F,MAAM,OAAO,WAAW;IACL,GAAG,GAAG,IAAI,GAAG,EAA0C,CAAC;IAEzE,GAAG,CAAC,MAAc,EAAE,OAAkC;QACpD,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjB,OAAO,GAAG,EAAE;YACV,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACpB,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,MAAe;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,CAAC,CAAC,MAAM,CAAC,CAAC;YACZ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,sCAAsC;gBACtC,OAAO,CAAC,KAAK,CAAC,kCAAkC,MAAM,QAAQ,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,50 @@
1
+ import { type Transport } from "./transport.js";
2
+ /** `window.chrome.webview` のうち使う部分 */
3
+ export interface WebView2Like {
4
+ postMessage(message: unknown): void;
5
+ addEventListener(type: "message", listener: (event: {
6
+ data: unknown;
7
+ }) => void): void;
8
+ removeEventListener(type: "message", listener: (event: {
9
+ data: unknown;
10
+ }) => void): void;
11
+ }
12
+ export interface WebView2TransportOptions {
13
+ /** 応答待ちの上限(既定 30000ms) */
14
+ timeoutMs?: number;
15
+ /** テスト用。省略時は window.chrome.webview */
16
+ webview?: WebView2Like;
17
+ /** 要求 id の生成。省略時は連番 + ランダム接頭辞 */
18
+ idGenerator?: () => string;
19
+ }
20
+ declare global {
21
+ interface Window {
22
+ chrome?: {
23
+ webview?: WebView2Like;
24
+ };
25
+ }
26
+ }
27
+ export declare function getWebView2(): WebView2Like | undefined;
28
+ /**
29
+ * WebView2 の postMessage / message イベントに JSON-RPC を載せる transport。
30
+ * Web → Host はオブジェクトをそのまま postMessage(Host は WebMessageAsJson で受ける)。
31
+ * Host → Web は PostWebMessageAsJson(e.data がオブジェクト)を想定するが、
32
+ * PostWebMessageAsString で JSON 文字列が来た場合も解釈する。
33
+ */
34
+ export declare class WebView2Transport implements Transport {
35
+ static isAvailable(): boolean;
36
+ private readonly webview;
37
+ private readonly timeoutMs;
38
+ private readonly nextId;
39
+ private readonly pending;
40
+ private readonly listeners;
41
+ private disposed;
42
+ constructor(options?: WebView2TransportOptions);
43
+ call(method: string, params: unknown): Promise<unknown>;
44
+ on(method: string, handler: (params: unknown) => void): () => void;
45
+ /** message リスナを外し、待機中の要求をすべて reject する */
46
+ dispose(): void;
47
+ get pendingCount(): number;
48
+ private readonly onMessage;
49
+ }
50
+ //# sourceMappingURL=webview2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webview2.d.ts","sourceRoot":"","sources":["../src/webview2.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAC;AAExB,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IACtF,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1F;AAED,MAAM,WAAW,wBAAwB;IACvC,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,YAAY,CAAA;SAAE,CAAC;KACrC;CACF;AAED,wBAAgB,WAAW,IAAI,YAAY,GAAG,SAAS,CAGtD;AASD;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IACjD,MAAM,CAAC,WAAW,IAAI,OAAO;IAI7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,GAAE,wBAA6B;IAWlD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBvD,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAIlE,0CAA0C;IAC1C,OAAO,IAAI,IAAI;IAYf,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,OAAO,CAAC,QAAQ,CAAC,SAAS,CA0BxB;CACH"}
@@ -0,0 +1,111 @@
1
+ import { BridgeDisposedError, BridgeError, BridgeTimeoutError, isJsonRpcNotification, isJsonRpcResponse, ListenerMap, } from "./transport.js";
2
+ export function getWebView2() {
3
+ if (typeof window === "undefined")
4
+ return undefined;
5
+ return window.chrome?.webview;
6
+ }
7
+ /**
8
+ * WebView2 の postMessage / message イベントに JSON-RPC を載せる transport。
9
+ * Web → Host はオブジェクトをそのまま postMessage(Host は WebMessageAsJson で受ける)。
10
+ * Host → Web は PostWebMessageAsJson(e.data がオブジェクト)を想定するが、
11
+ * PostWebMessageAsString で JSON 文字列が来た場合も解釈する。
12
+ */
13
+ export class WebView2Transport {
14
+ static isAvailable() {
15
+ return getWebView2() !== undefined;
16
+ }
17
+ webview;
18
+ timeoutMs;
19
+ nextId;
20
+ pending = new Map();
21
+ listeners = new ListenerMap();
22
+ disposed = false;
23
+ constructor(options = {}) {
24
+ const webview = options.webview ?? getWebView2();
25
+ if (!webview) {
26
+ throw new Error("window.chrome.webview is not available (not running inside WebView2)");
27
+ }
28
+ this.webview = webview;
29
+ this.timeoutMs = options.timeoutMs ?? 30_000;
30
+ this.nextId = options.idGenerator ?? createIdGenerator();
31
+ this.webview.addEventListener("message", this.onMessage);
32
+ }
33
+ call(method, params) {
34
+ if (this.disposed)
35
+ return Promise.reject(new BridgeDisposedError(method));
36
+ const id = this.nextId();
37
+ const request = { jsonrpc: "2.0", id, method, params };
38
+ return new Promise((resolve, reject) => {
39
+ const timer = setTimeout(() => {
40
+ this.pending.delete(id);
41
+ reject(new BridgeTimeoutError(method, this.timeoutMs));
42
+ }, this.timeoutMs);
43
+ this.pending.set(id, { method, resolve, reject, timer });
44
+ try {
45
+ this.webview.postMessage(request);
46
+ }
47
+ catch (e) {
48
+ clearTimeout(timer);
49
+ this.pending.delete(id);
50
+ reject(e);
51
+ }
52
+ });
53
+ }
54
+ on(method, handler) {
55
+ return this.listeners.add(method, handler);
56
+ }
57
+ /** message リスナを外し、待機中の要求をすべて reject する */
58
+ dispose() {
59
+ if (this.disposed)
60
+ return;
61
+ this.disposed = true;
62
+ this.webview.removeEventListener("message", this.onMessage);
63
+ for (const [id, p] of this.pending) {
64
+ clearTimeout(p.timer);
65
+ p.reject(new BridgeDisposedError(p.method));
66
+ this.pending.delete(id);
67
+ }
68
+ this.listeners.clear();
69
+ }
70
+ get pendingCount() {
71
+ return this.pending.size;
72
+ }
73
+ onMessage = (event) => {
74
+ let data = event.data;
75
+ if (typeof data === "string") {
76
+ try {
77
+ data = JSON.parse(data);
78
+ }
79
+ catch {
80
+ return; // このブリッジ宛てではない文字列メッセージ
81
+ }
82
+ }
83
+ if (isJsonRpcResponse(data)) {
84
+ if (data.id === null) {
85
+ // Parse error 等、要求と対応づけられないエラー。待機中の要求は残す(タイムアウトで落ちる)
86
+ console.error("[webview2-bridge] response without id", data);
87
+ return;
88
+ }
89
+ const p = this.pending.get(String(data.id));
90
+ if (!p)
91
+ return;
92
+ this.pending.delete(String(data.id));
93
+ clearTimeout(p.timer);
94
+ if ("error" in data)
95
+ p.reject(new BridgeError(data.error, p.method));
96
+ else
97
+ p.resolve(data.result);
98
+ return;
99
+ }
100
+ if (isJsonRpcNotification(data)) {
101
+ this.listeners.dispatch(data.method, data.params);
102
+ }
103
+ };
104
+ }
105
+ function createIdGenerator() {
106
+ // ページのリロード後も id が衝突しないよう、接頭辞にランダム値を付ける
107
+ const prefix = Math.random().toString(36).slice(2, 8);
108
+ let counter = 0;
109
+ return () => `${prefix}-${++counter}`;
110
+ }
111
+ //# sourceMappingURL=webview2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webview2.js","sourceRoot":"","sources":["../src/webview2.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@ishibashi0112/webview2-bridge-client",
3
+ "version": "0.1.0",
4
+ "description": "Front-end runtime for webview2-bridge: typed JSON-RPC client over WebView2 postMessage (WebView2Transport), in-browser MemoryTransport for development, and zod validation on both ends",
5
+ "keywords": [
6
+ "webview2",
7
+ "winforms",
8
+ "json-rpc",
9
+ "zod",
10
+ "react",
11
+ "vite",
12
+ "postMessage",
13
+ "bridge"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "ishibashi0112",
17
+ "homepage": "https://github.com/ishibashi0112/webview2-bridge#readme",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/ishibashi0112/webview2-bridge.git",
21
+ "directory": "packages/client"
22
+ },
23
+ "bugs": "https://github.com/ishibashi0112/webview2-bridge/issues",
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "main": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "peerDependencies": {
43
+ "zod": "^4.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^5.9.3",
47
+ "vitest": "^4.1.11",
48
+ "zod": "^4.5.4"
49
+ },
50
+ "scripts": {
51
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json",
52
+ "test": "vitest run",
53
+ "typecheck": "tsc --noEmit -p tsconfig.json"
54
+ }
55
+ }