electron-effect-rpc 0.8.0 → 0.10.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/dist/kit.d.ts CHANGED
@@ -1,7 +1,19 @@
1
1
  import { Effect } from "effect";
2
- import type * as Runtime from "effect/Runtime";
2
+ import type * as Context from "effect/Context";
3
3
  import type { AnyEvent, AnyMethod, AnyStreamMethod, RpcContract, RpcEventPayload } from "./contract.ts";
4
- import { type ChannelPrefix, type EventDecodeMode, type EventPublisherDiagnostics, type EventSubscribe, type EventSubscriber, type IpcMainLike, type Implementations, type OnStreamFrame, type RendererWindowLike, type RpcClient, type RpcEndpoint, type RpcEndpointDiagnostics, type RpcEventPublisher, type RpcInvoke, type RpcResponseDecodeMode, type StreamImplementations, type StreamRpcClient, type StreamBufferOptions } from "./types.ts";
4
+ import { type ElectronModuleCandidate } from "./preload-bridge.ts";
5
+ import { type ChannelPrefix, type EventDecodeMode, type EventPublisherDiagnostics, type EventPublisherStats, type EventSubscribe, type EventSubscriber, type EventSubscriberDiagnostics, type IpcMainLike, type Implementations, type OnStreamFrame, type RendererWindowLike, type RpcClient, type RpcClientDiagnostics, type RpcEndpoint, type RpcEndpointDiagnostics, type RpcEventPublisher, type RpcInvoke, type RpcResponseDecodeMode, type StreamImplementations, type StreamRpcClient, type StreamBufferOptions } from "./types.ts";
6
+ /**
7
+ * Narrow surface the preload script exposes to the renderer.
8
+ *
9
+ * Implementations are responsible for applying the kit's channel prefixes:
10
+ * `invoke(method, payload)` must call `ipcRenderer.invoke(channelPrefix.rpc +
11
+ * method, payload)`, `subscribe(name, ...)` must listen on
12
+ * `channelPrefix.event + name`, and `onStreamFrame` must listen on
13
+ * `channelPrefix.rpc + "sf"`. The bridge produced by `ipc.preload()` does this
14
+ * for you; hand-written bridges that skip the prefixes fail with
15
+ * `invoke_failed` defects at runtime.
16
+ */
5
17
  export type IpcBridge = {
6
18
  readonly invoke: RpcInvoke;
7
19
  readonly subscribe: EventSubscribe;
@@ -25,7 +37,7 @@ export type IpcKitOptions<C extends RpcContract<readonly AnyMethod[], readonly A
25
37
  type IpcMainOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>, R> = {
26
38
  readonly ipcMain: IpcMainLike;
27
39
  readonly handlers: Implementations<C, R>;
28
- readonly runtime: Runtime.Runtime<R>;
40
+ readonly context: Context.Context<R>;
29
41
  readonly getWindows: () => ReadonlyArray<RendererWindowLike>;
30
42
  readonly maxQueueSize?: number;
31
43
  readonly streamHandlers?: StreamImplementations<C, R>;
@@ -36,7 +48,14 @@ type IpcMainOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEven
36
48
  };
37
49
  type IpcPreloadOptions = {
38
50
  readonly global?: string;
39
- readonly electronModule?: unknown;
51
+ readonly electronModule?: ElectronModuleCandidate;
52
+ };
53
+ type IpcRendererOptions = {
54
+ readonly diagnostics?: {
55
+ readonly rpc?: RpcClientDiagnostics;
56
+ readonly events?: EventSubscriberDiagnostics;
57
+ readonly stream?: RpcClientDiagnostics;
58
+ };
40
59
  };
41
60
  export type IpcMainHandle<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>> = {
42
61
  readonly endpoint: RpcEndpoint;
@@ -46,10 +65,7 @@ export type IpcMainHandle<C extends RpcContract<readonly AnyMethod[], readonly A
46
65
  readonly dispose: () => void;
47
66
  readonly isRunning: () => boolean;
48
67
  readonly publish: <E extends C["events"][number]>(event: E, payload: RpcEventPayload<E>) => Effect.Effect<void, never>;
49
- readonly stats: () => {
50
- readonly queued: number;
51
- readonly dropped: number;
52
- };
68
+ readonly stats: () => EventPublisherStats;
53
69
  };
54
70
  export type IpcKit<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>> = {
55
71
  readonly contract: C;
@@ -66,7 +82,7 @@ export type IpcKit<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent
66
82
  readonly bridge: IpcBridge;
67
83
  readonly expose: () => void;
68
84
  };
69
- readonly renderer: (bridge: IpcBridge) => {
85
+ readonly renderer: (bridge: IpcBridge, options?: IpcRendererOptions) => {
70
86
  readonly client: RpcClient<C>;
71
87
  readonly events: EventSubscriber<C>;
72
88
  readonly streamClient: StreamRpcClient<C>;
package/dist/kit.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kit.d.ts","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EACV,QAAQ,EACR,SAAS,EACT,eAAe,EACf,WAAW,EACX,eAAe,EAChB,MAAM,eAAe,CAAC;AAQvB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EAEpB,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,MAAM,GAAG,KAAK,IAAI;IACzD,QAAQ,EAAE,CAAC,IAAI,IAAI,GAAG,SAAS;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,CACvB,CAAC,SAAS,WAAW,CAAC,SAAS,SAAS,EAAE,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,eAAe,EAAE,CAAC,IAC1F;IACF,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrB,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,GAAG,CAAC,EAAE,qBAAqB,CAAC;QACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;KACnC,CAAC;IACF,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;CAC7C,CAAC;AAEF,KAAK,cAAc,CACjB,CAAC,SAAS,WAAW,CAAC,SAAS,SAAS,EAAE,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,eAAe,EAAE,CAAC,EAC5F,CAAC,IACC;IACF,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC7D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC;QACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,yBAAyB,CAAC;KAC7C,CAAC;CACH,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,aAAa,CACvB,CAAC,SAAS,WAAW,CAAC,SAAS,SAAS,EAAE,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,eAAe,EAAE,CAAC,IAC1F;IACF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAC9C,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,CAChB,CAAC,SAAS,WAAW,CAAC,SAAS,SAAS,EAAE,EAAE,SAAS,QAAQ,EAAE,EAAE,SAAS,eAAe,EAAE,CAAC,IAC1F;IACF,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;QACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;QAC9C,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;QAC1C,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;KAC5C,CAAC;IACF,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC;IACtE,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK;QACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;KAC7B,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK;QACxC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;QACpC,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;KAC9B,CAAC;CACH,CAAC;AAiBF,wBAAgB,YAAY,CAC1B,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,KAAK,CAAC,aAAa,SAAS,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,EAAE,EAExE,OAAO,EAAE,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,GAClE,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CA6LrD"}
1
+ {"version":3,"file":"kit.d.ts","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"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"}
package/dist/kit.js CHANGED
@@ -2,16 +2,21 @@ import { Effect } from "effect";
2
2
  import { createEventPublisher, createRpcEndpoint } from "./main.js";
3
3
  import { createBridgeAdaptersFromBindings, exposeIpcBridgeFromBindings, resolveElectronRendererBindings, } from "./preload-bridge.js";
4
4
  import { createEventSubscriber, createRpcClient, createStreamRpcClient } from "./renderer.js";
5
- import { defaultChannelPrefix, } from "./types.js";
5
+ import { assertValidChannelPrefix, defaultChannelPrefix, } from "./types.js";
6
6
  function loadElectronModule(electronModule) {
7
7
  if (electronModule !== undefined) {
8
8
  return electronModule;
9
9
  }
10
- if (typeof require === "function") {
10
+ try {
11
11
  return require("electron");
12
12
  }
13
- throw new Error("ipc.preload() could not load Electron synchronously. " +
14
- "In ESM preload files, pass it explicitly: ipc.preload({ electronModule: electron }).");
13
+ catch (cause) {
14
+ if (!(cause instanceof ReferenceError)) {
15
+ throw cause;
16
+ }
17
+ throw new Error("ipc.preload() could not load Electron synchronously. " +
18
+ "In ESM preload files, pass it explicitly: ipc.preload({ electronModule: electron }).", { cause });
19
+ }
15
20
  }
16
21
  export function createIpcKit(options) {
17
22
  const normalizeStreamBuffer = (buffer) => {
@@ -27,7 +32,7 @@ export function createIpcKit(options) {
27
32
  };
28
33
  const contract = options.contract;
29
34
  const channelPrefix = options.channelPrefix
30
- ? { ...options.channelPrefix }
35
+ ? assertValidChannelPrefix({ ...options.channelPrefix })
31
36
  : { ...defaultChannelPrefix };
32
37
  const bridgeGlobal = options.bridge?.global ?? "api";
33
38
  const rpcDecodeMode = options.decode?.rpc ?? "envelope";
@@ -35,7 +40,7 @@ export function createIpcKit(options) {
35
40
  const streamBuffer = normalizeStreamBuffer(options.streamBuffer);
36
41
  const main = (mainOptions) => {
37
42
  const endpoint = createRpcEndpoint(contract, mainOptions.ipcMain, mainOptions.handlers, {
38
- runtime: mainOptions.runtime,
43
+ context: mainOptions.context,
39
44
  channelPrefix,
40
45
  diagnostics: mainOptions.diagnostics?.rpc,
41
46
  streamHandlers: mainOptions.streamHandlers,
@@ -131,7 +136,7 @@ export function createIpcKit(options) {
131
136
  },
132
137
  };
133
138
  };
134
- const renderer = (bridge) => {
139
+ const renderer = (bridge, rendererOptions) => {
135
140
  const hasStreamMethods = (contract.streamMethods?.length ?? 0) > 0;
136
141
  if (hasStreamMethods && !bridge.onStreamFrame) {
137
142
  throw new Error("Contract defines stream methods but bridge.onStreamFrame is missing. " +
@@ -143,6 +148,7 @@ export function createIpcKit(options) {
143
148
  invoke: bridge.invoke,
144
149
  onStreamFrame: bridge.onStreamFrame,
145
150
  streamBuffer,
151
+ diagnostics: rendererOptions?.diagnostics?.stream,
146
152
  });
147
153
  }
148
154
  const emptyStreamClient = Object.create(null);
@@ -150,10 +156,12 @@ export function createIpcKit(options) {
150
156
  client: createRpcClient(contract, {
151
157
  invoke: bridge.invoke,
152
158
  rpcDecodeMode,
159
+ diagnostics: rendererOptions?.diagnostics?.rpc,
153
160
  }),
154
161
  events: createEventSubscriber(contract, {
155
162
  subscribe: bridge.subscribe,
156
163
  decodeMode: eventDecodeMode,
164
+ diagnostics: rendererOptions?.diagnostics?.events,
157
165
  }),
158
166
  streamClient: streamHandle?.client ?? emptyStreamClient,
159
167
  dispose: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EAQZ,MAAM,eAAe,CAAC;AAcvB,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAGvB,MAAM,YAAY,CAAC;AAkCpB,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,KAAK,CAAC,aAAa,SAAS,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,EAAE,EACxE,CAAC,GAAG,KAAK,EAET,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EACrD,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,eAAe,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,EAChF,OAAO,EAAE,kBAAkB,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,GAC1E,WAAW,CAwbb;AAmBD,wBAAgB,oBAAoB,CAClC,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,KAAK,CAAC,aAAa,SAAS,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,EAAE,EAExE,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EACtD,OAAO,EAAE,qBAAqB,GAC7B,iBAAiB,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAmNhE"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EAQZ,MAAM,eAAe,CAAC;AAavB,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,KAAK,qBAAqB,EAE1B,KAAK,eAAe,EAEpB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAEvB,MAAM,YAAY,CAAC;AAmCpB,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,KAAK,CAAC,aAAa,SAAS,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,EAAE,EACxE,CAAC,GAAG,KAAK,EAET,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EACrD,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,eAAe,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,EAChF,OAAO,EAAE,kBAAkB,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,GAC1E,WAAW,CAoeb;AAmBD,wBAAgB,oBAAoB,CAClC,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,KAAK,CAAC,aAAa,SAAS,aAAa,CAAC,eAAe,CAAC,GAAG,SAAS,EAAE,EAExE,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,EACtD,OAAO,EAAE,qBAAqB,GAC7B,iBAAiB,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAuNhE"}
package/dist/main.js CHANGED
@@ -1,34 +1,35 @@
1
- import * as S from "@effect/schema/Schema";
2
- import { Cause, Effect, Exit, FiberId, Stream } from "effect";
3
- import * as Runtime from "effect/Runtime";
1
+ import * as S from "effect/Schema";
2
+ import { Cause, Effect, Exit, Fiber, Result, Stream } from "effect";
3
+ import { isFunctionValue, isNumberValue, isRecord, isStringValue, toDiagnosticCause, } from "./boundary.js";
4
4
  import { isNoErrorSchema } from "./contract.js";
5
- import { extractErrorTag, formatUnknown, isRecord, safelyCall, toDefectEnvelope, } from "./protocol.js";
6
- import { defaultChannelPrefix, } from "./types.js";
5
+ import { extractErrorTag, formatUnknown, safelyCall, toDefectEnvelope, } from "./protocol.js";
6
+ import { assertValidChannelPrefix, defaultChannelPrefix, } from "./types.js";
7
+ function readNamed(record, key) {
8
+ return record[key];
9
+ }
7
10
  function resolveChannelPrefix(prefix) {
8
- return prefix ?? defaultChannelPrefix;
11
+ return prefix ? assertValidChannelPrefix(prefix) : defaultChannelPrefix;
9
12
  }
10
13
  function isWebContentsLike(value) {
11
- if (!isRecord(value))
12
- return false;
13
- return (typeof value.id === "number" &&
14
- typeof value.isDestroyed === "function" &&
15
- typeof value.send === "function");
14
+ return (isRecord(value) &&
15
+ isNumberValue(value.id) &&
16
+ isFunctionValue(value.isDestroyed) &&
17
+ isFunctionValue(value.send) &&
18
+ (value.once === undefined || isFunctionValue(value.once)) &&
19
+ (value.removeListener === undefined || isFunctionValue(value.removeListener)));
20
+ }
21
+ function parseWebContentsLike(value) {
22
+ return isWebContentsLike(value) ? value : null;
16
23
  }
17
24
  function extractSender(event) {
18
25
  if (!isRecord(event))
19
26
  return null;
20
- return isWebContentsLike(event.sender) ? event.sender : null;
21
- }
22
- function isImplementation(value) {
23
- return typeof value === "function";
24
- }
25
- function isStreamImplementation(value) {
26
- return typeof value === "function";
27
+ return parseWebContentsLike(event.sender);
27
28
  }
28
29
  export function createRpcEndpoint(contract, ipc, implementations, options) {
29
30
  const channelPrefix = resolveChannelPrefix(options.channelPrefix);
30
31
  const diagnostics = options.diagnostics;
31
- const runPromiseExit = Runtime.runPromiseExit(options.runtime);
32
+ const runPromiseExit = Effect.runPromiseExitWith(options.context);
32
33
  const implementationsByName = implementations;
33
34
  const methodNames = new Set(contract.methods.map((method) => method.name));
34
35
  for (const name in implementations) {
@@ -39,21 +40,21 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
39
40
  function reportProtocolError(method, response, cause) {
40
41
  safelyCall(diagnostics?.onProtocolError, {
41
42
  method,
42
- response,
43
- cause,
43
+ response: toDiagnosticCause(response),
44
+ cause: toDiagnosticCause(cause),
44
45
  });
45
46
  }
46
47
  const listeners = new Map();
47
48
  for (const method of contract.methods) {
48
- const impl = implementationsByName[method.name];
49
- if (!isImplementation(impl)) {
49
+ const impl = readNamed(implementationsByName, method.name);
50
+ if (!isFunctionValue(impl)) {
50
51
  throw new Error(`Missing implementation for RPC method: ${method.name}`);
51
52
  }
52
53
  const decodeInput = S.decodeUnknownSync(method.req);
53
54
  const encodeSuccess = S.encodeSync(method.res);
54
55
  const encodeFailure = isNoErrorSchema(method.err) ? null : S.encodeSync(method.err);
55
56
  const channel = `${channelPrefix.rpc}${method.name}`;
56
- listeners.set(channel, async function handleRpcRequest(_event, rawPayload) {
57
+ listeners.set(channel, async function handleRpcRequest(event, rawPayload) {
57
58
  let input;
58
59
  try {
59
60
  input = decodeInput(rawPayload);
@@ -63,13 +64,13 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
63
64
  scope: "rpc-request",
64
65
  name: method.name,
65
66
  payload: rawPayload,
66
- cause,
67
+ cause: toDiagnosticCause(cause),
67
68
  });
68
69
  return toDefectEnvelope(cause, `RPC ${method.name} request decode failed`);
69
70
  }
70
71
  let effect;
71
72
  try {
72
- effect = impl(input);
73
+ effect = impl(input, { sender: extractSender(event) });
73
74
  }
74
75
  catch (cause) {
75
76
  return toDefectEnvelope(cause, `RPC ${method.name} implementation threw`);
@@ -87,7 +88,7 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
87
88
  return toDefectEnvelope(cause, `RPC ${method.name} success encoding failed`);
88
89
  }
89
90
  }
90
- const failure = Cause.failureOption(exit.cause);
91
+ const failure = Cause.findErrorOption(exit.cause);
91
92
  if (failure._tag === "Some") {
92
93
  if (!encodeFailure) {
93
94
  return toDefectEnvelope(failure.value, `RPC ${method.name} returned a typed failure, but method declares NoError`);
@@ -106,9 +107,9 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
106
107
  return toDefectEnvelope(cause, `RPC ${method.name} failure encoding failed`);
107
108
  }
108
109
  }
109
- const defect = Cause.dieOption(exit.cause);
110
- if (defect._tag === "Some") {
111
- return toDefectEnvelope(defect.value, `RPC ${method.name} defect`);
110
+ const defect = Cause.findDefect(exit.cause);
111
+ if (Result.isSuccess(defect)) {
112
+ return toDefectEnvelope(defect.success, `RPC ${method.name} defect`);
112
113
  }
113
114
  return toDefectEnvelope(exit.cause, `RPC ${method.name} interrupted`);
114
115
  });
@@ -121,6 +122,11 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
121
122
  if (streamMethods.length > 0 && !streamHandlerImpls) {
122
123
  throw new Error("Contract defines stream methods but no streamHandlers were provided.");
123
124
  }
125
+ if (streamMethods.length === 0 &&
126
+ streamHandlerImpls &&
127
+ Object.keys(streamHandlerImpls).length > 0) {
128
+ throw new Error("streamHandlers were provided but the contract defines no stream methods.");
129
+ }
124
130
  if (streamMethods.length > 0 && streamHandlerImpls) {
125
131
  const streamMethodNames = new Set(streamMethods.map((m) => m.name));
126
132
  for (const name in streamHandlerImpls) {
@@ -128,10 +134,10 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
128
134
  throw new Error(`Stream implementation provided for unknown stream method: ${name}`);
129
135
  }
130
136
  }
131
- const runFork = Runtime.runFork(options.runtime);
137
+ const runFork = Effect.runForkWith(options.context);
132
138
  for (const method of streamMethods) {
133
- const impl = streamHandlerImpls[method.name];
134
- if (!isStreamImplementation(impl)) {
139
+ const impl = readNamed(streamHandlerImpls, method.name);
140
+ if (!isFunctionValue(impl)) {
135
141
  throw new Error(`Missing implementation for stream method: ${method.name}`);
136
142
  }
137
143
  const decodeInput = S.decodeUnknownSync(method.req);
@@ -144,7 +150,7 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
144
150
  }
145
151
  const streamId = rawPayload.streamId;
146
152
  const rawData = rawPayload.data;
147
- if (typeof streamId !== "string" || streamId.length === 0) {
153
+ if (!isStringValue(streamId) || streamId.length === 0) {
148
154
  return toDefectEnvelope("Invalid streamId");
149
155
  }
150
156
  if (activeStreams.has(streamId)) {
@@ -162,8 +168,8 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
162
168
  const decodeCtx = {
163
169
  scope: "stream-request",
164
170
  name: method.name,
165
- payload: rawData,
166
- cause,
171
+ payload: toDiagnosticCause(rawData),
172
+ cause: toDiagnosticCause(cause),
167
173
  };
168
174
  safelyCall(diagnostics?.onDecodeFailure, decodeCtx);
169
175
  return toDefectEnvelope(cause, `Stream ${method.name} request decode failed`);
@@ -179,13 +185,13 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
179
185
  }).pipe(Effect.ignore);
180
186
  let handlerStream;
181
187
  try {
182
- handlerStream = impl(input);
188
+ handlerStream = impl(input, { sender });
183
189
  }
184
190
  catch (cause) {
185
191
  return toDefectEnvelope(cause, `Stream ${method.name} implementation threw`);
186
192
  }
187
193
  const buildTerminalFrame = (cause) => {
188
- const failure = Cause.failureOption(cause);
194
+ const failure = Cause.findErrorOption(cause);
189
195
  if (failure._tag === "Some") {
190
196
  if (encodeFailure) {
191
197
  try {
@@ -198,39 +204,71 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
198
204
  },
199
205
  };
200
206
  }
201
- catch {
202
- // encoding failed, fall through to defect
207
+ catch (encodeCause) {
208
+ return {
209
+ type: "defect",
210
+ streamId,
211
+ message: `Stream ${method.name} failure encoding failed: ${formatUnknown(encodeCause)}`,
212
+ };
203
213
  }
204
214
  }
205
- return { type: "defect", streamId, message: formatUnknown(failure.value) };
215
+ return {
216
+ type: "defect",
217
+ streamId,
218
+ message: `Stream ${method.name} returned a typed failure, but method declares NoError: ${formatUnknown(failure.value)}`,
219
+ };
206
220
  }
207
- if (Cause.isInterruptedOnly(cause)) {
221
+ if (Cause.hasInterruptsOnly(cause)) {
208
222
  return { type: "end", streamId };
209
223
  }
210
- const defect = Cause.dieOption(cause);
224
+ const defect = Cause.findDefect(cause);
211
225
  return {
212
226
  type: "defect",
213
227
  streamId,
214
- message: defect._tag === "Some" ? formatUnknown(defect.value) : "Stream failed unexpectedly",
228
+ message: Result.isSuccess(defect)
229
+ ? formatUnknown(defect.success)
230
+ : "Stream failed unexpectedly",
215
231
  };
216
232
  };
217
- const streamEffect = handlerStream.pipe(Stream.mapEffect((chunk) => Effect.try({
218
- try: () => {
219
- if (sender.isDestroyed())
220
- return;
221
- sender.send(sfChannel, { type: "data", streamId, payload: encodeChunk(chunk) });
222
- },
223
- catch: () => undefined,
224
- }).pipe(Effect.ignore)), Stream.runDrain, Effect.andThen(() => trySend({ type: "end", streamId })), Effect.catchAllCause((cause) => sender.isDestroyed() ? Effect.void : trySend(buildTerminalFrame(cause))), Effect.ensuring(Effect.sync(() => {
225
- activeStreams.delete(streamId);
226
- })));
227
233
  // Reserve entry BEFORE forking
228
234
  const entry = {
229
235
  fiber: null,
230
236
  senderId: sender.id,
231
237
  };
238
+ const onSenderDestroyed = () => {
239
+ entry.fiber?.interruptUnsafe();
240
+ };
241
+ const streamEffect = handlerStream.pipe(Stream.mapEffect((chunk) => Effect.suspend(() => {
242
+ // A destroyed renderer can never consume more chunks:
243
+ // terminate the pipeline instead of draining the source.
244
+ if (sender.isDestroyed()) {
245
+ return Effect.interrupt;
246
+ }
247
+ return Effect.try({
248
+ try: () => sender.send(sfChannel, { type: "data", streamId, payload: encodeChunk(chunk) }),
249
+ catch: () => undefined,
250
+ }).pipe(Effect.ignore);
251
+ })), Stream.runDrain, Effect.andThen(() => trySend({ type: "end", streamId })), Effect.catchCause((cause) => sender.isDestroyed() ? Effect.void : trySend(buildTerminalFrame(cause))), Effect.ensuring(Effect.sync(() => {
252
+ activeStreams.delete(streamId);
253
+ if (sender.removeListener) {
254
+ sender.removeListener("destroyed", onSenderDestroyed);
255
+ }
256
+ })));
232
257
  activeStreams.set(streamId, entry);
233
- const fiber = runFork(streamEffect);
258
+ if (sender.once) {
259
+ sender.once("destroyed", onSenderDestroyed);
260
+ }
261
+ let fiber;
262
+ try {
263
+ fiber = runFork(streamEffect);
264
+ }
265
+ catch (cause) {
266
+ activeStreams.delete(streamId);
267
+ if (sender.removeListener) {
268
+ sender.removeListener("destroyed", onSenderDestroyed);
269
+ }
270
+ return toDefectEnvelope(cause, `Stream ${method.name} failed to start`);
271
+ }
234
272
  entry.fiber = fiber;
235
273
  const response = {
236
274
  type: "success",
@@ -267,7 +305,7 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
267
305
  return { cancelled: false };
268
306
  }
269
307
  const streamId = rawPayload.streamId;
270
- if (typeof streamId !== "string")
308
+ if (!isStringValue(streamId))
271
309
  return { cancelled: false };
272
310
  const entry = activeStreams.get(streamId);
273
311
  if (!entry)
@@ -278,7 +316,7 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
278
316
  return { cancelled: false };
279
317
  // Interrupt the fiber
280
318
  if (entry.fiber) {
281
- entry.fiber.unsafeInterruptAsFork(FiberId.none);
319
+ entry.fiber.interruptUnsafe();
282
320
  }
283
321
  return { cancelled: true };
284
322
  });
@@ -305,7 +343,7 @@ export function createRpcEndpoint(contract, ipc, implementations, options) {
305
343
  // Interrupt all active stream fibers first
306
344
  for (const entry of activeStreams.values()) {
307
345
  if (entry.fiber) {
308
- entry.fiber.unsafeInterruptAsFork(FiberId.none);
346
+ entry.fiber.interruptUnsafe();
309
347
  }
310
348
  }
311
349
  activeStreams.clear();
@@ -404,12 +442,12 @@ export function createEventPublisher(_contract, options) {
404
442
  safelyCall(diagnostics?.onDecodeFailure, {
405
443
  scope: "event-payload",
406
444
  name: item.event.name,
407
- payload: item.payload,
408
- cause,
445
+ payload: toDiagnosticCause(item.payload),
446
+ cause: toDiagnosticCause(cause),
409
447
  });
410
448
  safelyCall(diagnostics?.onDroppedEvent, {
411
449
  event: item.event.name,
412
- payload: item.payload,
450
+ payload: toDiagnosticCause(item.payload),
413
451
  reason: "encoding_failed",
414
452
  queued: queue.length,
415
453
  dropped,
@@ -421,7 +459,7 @@ export function createEventPublisher(_contract, options) {
421
459
  dropped += 1;
422
460
  safelyCall(diagnostics?.onDroppedEvent, {
423
461
  event: item.event.name,
424
- payload: item.payload,
462
+ payload: toDiagnosticCause(item.payload),
425
463
  reason: "window_unavailable",
426
464
  queued: queue.length,
427
465
  dropped,
@@ -434,7 +472,7 @@ export function createEventPublisher(_contract, options) {
434
472
  dropped += 1;
435
473
  safelyCall(diagnostics?.onDroppedEvent, {
436
474
  event: item.event.name,
437
- payload: item.payload,
475
+ payload: toDiagnosticCause(item.payload),
438
476
  reason: "window_unavailable",
439
477
  queued: queue.length,
440
478
  dropped,
@@ -448,12 +486,12 @@ export function createEventPublisher(_contract, options) {
448
486
  dropped += 1;
449
487
  safelyCall(diagnostics?.onDispatchFailure, {
450
488
  event: item.event.name,
451
- payload: item.payload,
452
- cause,
489
+ payload: toDiagnosticCause(item.payload),
490
+ cause: toDiagnosticCause(cause),
453
491
  });
454
492
  safelyCall(diagnostics?.onDroppedEvent, {
455
493
  event: item.event.name,
456
- payload: item.payload,
494
+ payload: toDiagnosticCause(item.payload),
457
495
  reason: "dispatch_failed",
458
496
  queued: queue.length,
459
497
  dropped,
@@ -467,7 +505,10 @@ export function createEventPublisher(_contract, options) {
467
505
  }
468
506
  draining = true;
469
507
  try {
470
- while (running && !disposed && queue.length > 0) {
508
+ while (queue.length > 0) {
509
+ if (!running || disposed) {
510
+ break;
511
+ }
471
512
  const next = queue.shift();
472
513
  if (!next) {
473
514
  continue;
@@ -489,7 +530,7 @@ export function createEventPublisher(_contract, options) {
489
530
  if (evicted) {
490
531
  safelyCall(diagnostics?.onDroppedEvent, {
491
532
  event: evicted.event.name,
492
- payload: evicted.payload,
533
+ payload: toDiagnosticCause(evicted.payload),
493
534
  reason: "queue_full",
494
535
  queued: queue.length,
495
536
  dropped,
@@ -1,8 +1,22 @@
1
- import { type ChannelPrefix, type EventSubscribe, type RpcInvoke } from "./types.ts";
1
+ import { type IpcEncodedValue } from "./boundary.ts";
2
+ import { type ChannelPrefix, type EventSubscribe, type IpcInvokeEvent, type OnStreamFrame, type RpcInvoke } from "./types.ts";
3
+ export type ExposedRpcApi = {
4
+ readonly invoke: RpcInvoke;
5
+ readonly onStreamFrame: OnStreamFrame;
6
+ };
7
+ export type ExposedEventsApi = {
8
+ readonly subscribe: EventSubscribe;
9
+ };
10
+ export type ExposedIpcApi = {
11
+ readonly invoke: RpcInvoke;
12
+ readonly subscribe: EventSubscribe;
13
+ readonly onStreamFrame: OnStreamFrame;
14
+ };
15
+ export type ExposedBridgeValue = ExposedRpcApi | ExposedEventsApi | ExposedIpcApi;
2
16
  export type BridgeAdapters = {
3
17
  readonly invoke: RpcInvoke;
4
18
  readonly subscribe: EventSubscribe;
5
- readonly onStreamFrame: (listener: (frame: unknown) => void) => () => void;
19
+ readonly onStreamFrame: OnStreamFrame;
6
20
  };
7
21
  export type BridgeAdaptersOptions = {
8
22
  readonly channelPrefix?: ChannelPrefix;
@@ -15,18 +29,32 @@ export type IpcBridgeExposureOptions = BridgeAdaptersOptions & {
15
29
  readonly global?: string;
16
30
  };
17
31
  type ContextBridgeLike = {
18
- readonly exposeInMainWorld: (name: string, value: Record<string, unknown>) => void;
32
+ readonly exposeInMainWorld: (name: string, value: ExposedBridgeValue) => void;
19
33
  };
20
34
  type IpcRendererLike = {
21
- readonly invoke: (channel: string, payload: unknown) => Promise<unknown>;
22
- readonly on: (channel: string, handler: (event: unknown, payload: unknown) => void) => void;
23
- readonly removeListener: (channel: string, handler: (event: unknown, payload: unknown) => void) => void;
35
+ readonly invoke: (channel: string, payload: IpcEncodedValue) => Promise<IpcEncodedValue>;
36
+ readonly on: (channel: string, handler: (event: IpcInvokeEvent, payload: IpcEncodedValue) => void) => void;
37
+ readonly removeListener: (channel: string, handler: (event: IpcInvokeEvent, payload: IpcEncodedValue) => void) => void;
24
38
  };
25
- type ElectronRendererBindings = {
39
+ export type ElectronRendererBindings = {
26
40
  readonly contextBridge: ContextBridgeLike;
27
41
  readonly ipcRenderer: IpcRendererLike;
28
42
  };
29
- export declare function resolveElectronRendererBindings(moduleCandidate: unknown): ElectronRendererBindings;
43
+ type ElectronRuntimeFunction = (...arguments_: never[]) => void;
44
+ type ElectronDirectModuleCandidate = {
45
+ readonly contextBridge: {
46
+ readonly exposeInMainWorld: ElectronRuntimeFunction;
47
+ };
48
+ readonly ipcRenderer: {
49
+ readonly invoke: ElectronRuntimeFunction;
50
+ readonly on: ElectronRuntimeFunction;
51
+ readonly removeListener: ElectronRuntimeFunction;
52
+ };
53
+ };
54
+ export type ElectronModuleCandidate = ElectronDirectModuleCandidate | {
55
+ readonly default: ElectronModuleCandidate;
56
+ };
57
+ export declare function resolveElectronRendererBindings<T>(moduleCandidate: T): ElectronRendererBindings;
30
58
  export declare function createBridgeAdaptersFromBindings(bindings: ElectronRendererBindings, options?: BridgeAdaptersOptions): BridgeAdapters;
31
59
  export declare function exposeRpcBridgeFromBindings(bindings: ElectronRendererBindings, options?: BridgeExposureOptions): void;
32
60
  export declare function exposeIpcBridgeFromBindings(bindings: ElectronRendererBindings, options?: IpcBridgeExposureOptions): void;
@@ -1 +1 @@
1
- {"version":3,"file":"preload-bridge.d.ts","sourceRoot":"","sources":["../src/preload-bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAC5E,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,GAAG;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAAG;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACpF,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,QAAQ,CAAC,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC5F,QAAQ,CAAC,cAAc,EAAE,CACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,KAChD,IAAI,CAAC;CACX,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC,CAAC;AAeF,wBAAgB,+BAA+B,CAC7C,eAAe,EAAE,OAAO,GACvB,wBAAwB,CAqB1B;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,cAAc,CAgChB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAiBN;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,wBAAwB,GACjC,IAAI,CAaN"}
1
+ {"version":3,"file":"preload-bridge.d.ts","sourceRoot":"","sources":["../src/preload-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAElF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,GAAG;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAAG;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/E,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACzF,QAAQ,CAAC,EAAE,EAAE,CACX,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,KAAK,IAAI,KAC/D,IAAI,CAAC;IACV,QAAQ,CAAC,cAAc,EAAE,CACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,KAAK,IAAI,KAC/D,IAAI,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC,CAAC;AAEF,KAAK,uBAAuB,GAAG,CAAC,GAAG,UAAU,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;AAEhE,KAAK,6BAA6B,GAAG;IACnC,QAAQ,CAAC,aAAa,EAAE;QACtB,QAAQ,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;KACrD,CAAC;IACF,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;QACzC,QAAQ,CAAC,EAAE,EAAE,uBAAuB,CAAC;QACrC,QAAQ,CAAC,cAAc,EAAE,uBAAuB,CAAC;KAClD,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B,6BAA6B,GAC7B;IAAE,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAA;CAAE,CAAC;AA2BlD,wBAAgB,+BAA+B,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,GAAG,wBAAwB,CAc/F;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,cAAc,CAkChB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAiBN;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,CAAC,EAAE,wBAAwB,GACjC,IAAI,CAaN"}