electron-effect-rpc 0.4.0 → 0.6.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/README.md CHANGED
@@ -10,20 +10,24 @@ This package is ESM-only. It targets modern Electron runtimes and assumes an
10
10
  ESM-capable build pipeline.
11
11
 
12
12
  ## Features
13
- - Single shared contract for methods and events.
13
+
14
+ - Single shared contract for methods, events, and streaming RPC.
14
15
  - Single shared kit config to eliminate cross-process prefix drift.
15
16
  - End-to-end schema validation at IPC boundaries.
16
17
  - Effect-first renderer RPC with typed domain and defect channels.
18
+ - Streaming RPC: handlers return `Stream.Stream`, clients consume `Stream.Stream`.
17
19
  - Effect-native main handlers with explicit runtime injection.
18
20
  - Explicit lifecycle handles and bounded event queue backpressure.
19
21
  - Structured diagnostics hooks for decode/protocol/dispatch failures.
20
22
 
21
23
  ## Requirements
24
+
22
25
  - Electron with context isolation enabled.
23
26
  - ESM-capable bundling.
24
27
  - Peer dependencies: `effect`, `@effect/schema`, `electron`.
25
28
 
26
29
  ## Installation
30
+
27
31
  ```sh
28
32
  bun add electron-effect-rpc effect @effect/schema
29
33
  ```
@@ -31,15 +35,12 @@ bun add electron-effect-rpc effect @effect/schema
31
35
  ## Quickstart (Kit-First)
32
36
 
33
37
  ### 1) Define contract and kit once
38
+
34
39
  ```ts
35
40
  import * as S from "@effect/schema/Schema";
36
- import { createIpcKit, defineContract, event, rpc } from "electron-effect-rpc";
41
+ import { createIpcKit, defineContract, event, rpc, streamRpc } from "electron-effect-rpc";
37
42
 
38
- export const GetAppVersion = rpc(
39
- "GetAppVersion",
40
- S.Struct({}),
41
- S.Struct({ version: S.String })
42
- );
43
+ export const GetAppVersion = rpc("GetAppVersion", S.Struct({}), S.Struct({ version: S.String }));
43
44
 
44
45
  export const WorkUnitProgress = event(
45
46
  "WorkUnitProgress",
@@ -47,12 +48,19 @@ export const WorkUnitProgress = event(
47
48
  requestId: S.String,
48
49
  chunk: S.String,
49
50
  done: S.Boolean,
50
- })
51
+ }),
52
+ );
53
+
54
+ export const StreamAiGeneration = streamRpc(
55
+ "StreamAiGeneration",
56
+ S.Struct({ prompt: S.String }),
57
+ S.Struct({ delta: S.String }),
51
58
  );
52
59
 
53
60
  const contract = defineContract({
54
61
  methods: [GetAppVersion] as const,
55
62
  events: [WorkUnitProgress] as const,
63
+ streamMethods: [StreamAiGeneration] as const,
56
64
  });
57
65
 
58
66
  export const ipc = createIpcKit({
@@ -64,9 +72,10 @@ export const ipc = createIpcKit({
64
72
  ```
65
73
 
66
74
  ### 2) Main process
75
+
67
76
  ```ts
68
77
  import { app, ipcMain } from "electron";
69
- import { Effect } from "effect";
78
+ import { Effect, Stream } from "effect";
70
79
  import * as Runtime from "effect/Runtime";
71
80
  import { ipc, WorkUnitProgress } from "./shared-ipc.ts";
72
81
 
@@ -75,20 +84,27 @@ const mainRpc = ipc.main({
75
84
  handlers: {
76
85
  GetAppVersion: () => Effect.succeed({ version: app.getVersion() }),
77
86
  },
87
+ streamHandlers: {
88
+ StreamAiGeneration: ({ prompt }) =>
89
+ Stream.fromIterable(prompt.split(" ")).pipe(Stream.map((word) => ({ delta: word + " " }))),
90
+ },
78
91
  runtime: Runtime.defaultRuntime,
79
- getWindow: () => mainWindow,
92
+ getWindows: () => [mainWindow],
80
93
  });
81
94
 
82
95
  mainRpc.start();
83
96
 
84
- void Effect.runPromise(mainRpc.publish(WorkUnitProgress, {
85
- requestId: "req-1",
86
- chunk: "starting",
87
- done: false,
88
- }));
97
+ void Effect.runPromise(
98
+ mainRpc.publish(WorkUnitProgress, {
99
+ requestId: "req-1",
100
+ chunk: "starting",
101
+ done: false,
102
+ }),
103
+ );
89
104
  ```
90
105
 
91
106
  ### 3) Preload
107
+
92
108
  ```ts
93
109
  import { ipc } from "./shared-ipc.ts";
94
110
 
@@ -98,29 +114,39 @@ ipc.preload().expose();
98
114
  This exposes one global by default: `window.api`.
99
115
 
100
116
  ### 4) Renderer
117
+
101
118
  ```ts
102
- import { Effect } from "effect";
119
+ import { Effect, Stream } from "effect";
103
120
  import { ipc, WorkUnitProgress } from "./shared-ipc.ts";
104
121
 
105
- const { client, events } = ipc.renderer(window.api);
122
+ const { client, events, streamClient, dispose } = ipc.renderer(window.api);
106
123
  const { version } = await Effect.runPromise(client.GetAppVersion());
107
124
 
125
+ // Streaming RPC
126
+ await Effect.runPromise(
127
+ streamClient
128
+ .StreamAiGeneration({ prompt: "hello world" })
129
+ .pipe(Stream.runForEach((chunk) => Effect.sync(() => console.log(chunk.delta)))),
130
+ );
131
+
108
132
  const unsubscribe = events.subscribe(WorkUnitProgress, (payload) => {
109
133
  console.log(payload.chunk);
110
134
  });
111
135
 
112
136
  // later
113
137
  unsubscribe();
114
- events.dispose();
138
+ dispose();
115
139
  ```
116
140
 
117
141
  ### 5) Window typing
142
+
118
143
  ```ts
119
144
  declare global {
120
145
  interface Window {
121
146
  api: {
122
147
  invoke: (method: string, payload: unknown) => Promise<unknown>;
123
148
  subscribe: (name: string, handler: (payload: unknown) => void) => () => void;
149
+ onStreamFrame?: (listener: (frame: unknown) => void) => () => void;
124
150
  };
125
151
  }
126
152
  }
@@ -135,10 +161,27 @@ which includes a stable `code` discriminator:
135
161
  `request_encoding_failed`, `invoke_failed`,
136
162
  `success_payload_decoding_failed`, `failure_payload_decoding_failed`,
137
163
  `noerror_contract_violation`, `invalid_response_envelope`,
138
- `legacy_decode_failed`, and `remote_defect`.
164
+ `legacy_decode_failed`, `remote_defect`,
165
+ `stream_invoke_failed`, `stream_handshake_invalid`,
166
+ `stream_chunk_decode_failed`, and `stream_error_decode_failed`.
139
167
 
140
168
  ## Breaking Changes
141
169
 
170
+ `getWindow` was renamed to `getWindows` and now returns an array, enabling
171
+ multi-window event fan-out. Empty array replaces `null` for "no windows."
172
+
173
+ Before:
174
+
175
+ ```ts
176
+ getWindow: () => mainWindow,
177
+ ```
178
+
179
+ After:
180
+
181
+ ```ts
182
+ getWindows: () => [mainWindow],
183
+ ```
184
+
142
185
  Renderer RPC methods now return `Effect.Effect` instead of `Promise`, and
143
186
  `IpcMainHandle.emit` was removed in favor of `publish`.
144
187
 
@@ -159,6 +202,7 @@ await Effect.runPromise(mainRpc.publish(WorkUnitProgress, payload));
159
202
  ## Low-Level APIs (Still Supported)
160
203
 
161
204
  If you need direct control, keep using subpath entry points:
205
+
162
206
  - `electron-effect-rpc/contract`
163
207
  - `electron-effect-rpc/main`
164
208
  - `electron-effect-rpc/renderer`
@@ -169,8 +213,9 @@ If you need direct control, keep using subpath entry points:
169
213
  ## Root API Surface
170
214
 
171
215
  The root entry point exports:
216
+
172
217
  - `createIpcKit`
173
- - `rpc`, `event`, `defineContract`, `NoError`
218
+ - `rpc`, `event`, `streamRpc`, `defineContract`, `NoError`
174
219
  - Types: `IpcKit`, `IpcKitOptions`, `IpcMainHandle`, `IpcBridge`, `IpcBridgeGlobal`
175
220
 
176
221
  Low-level factories like `createRpcClient` remain subpath-only by design.
@@ -178,15 +223,19 @@ Low-level factories like `createRpcClient` remain subpath-only by design.
178
223
  ## Tutorials
179
224
 
180
225
  For deeper walkthroughs and production guidance:
226
+
181
227
  - [Tutorial Index](./docs/tutorials/README.md)
182
228
  - [First RPC: Main + Preload + Renderer](./docs/tutorials/01-first-rpc.md)
183
229
  - [Typed Errors, Defects, and Diagnostics](./docs/tutorials/02-typed-errors-defects-diagnostics.md)
184
230
  - [Events, Lifecycle, and Backpressure](./docs/tutorials/03-events-lifecycle-backpressure.md)
231
+ - [Streaming RPC](./docs/tutorials/04-streaming-rpc.md)
185
232
 
186
233
  ## Conventions
234
+
187
235
  - Relative imports use `.ts` extensions.
188
236
  - Package imports are extensionless.
189
237
  - No `index.ts` barrel files in subpath modules.
190
238
 
191
239
  ## License
240
+
192
241
  MIT
@@ -20,6 +20,22 @@ export interface RpcEvent<Payload extends SchemaNoContext, Context extends Schem
20
20
  export declare function event<const Name extends string, Payload extends SchemaNoContext, Context extends SchemaNoContext>(name: Name, payload: Payload, context: Context): RpcEvent<Payload, Context, Name>;
21
21
  export declare function event<const Name extends string, Payload extends SchemaNoContext>(name: Name, payload: Payload): RpcEvent<Payload, null, Name>;
22
22
  export declare const exitSchemaFor: <Name extends string, Req extends SchemaNoContext, Res extends SchemaNoContext, Err extends ErrorSchema>(method: RpcMethod<Name, Req, Res, Err>) => S.Exit<Res, Err, S.Defect>;
23
+ export interface StreamRpcMethod<Name extends string, Req extends SchemaNoContext, Chunk extends SchemaNoContext, Err extends ErrorSchema = NoError> {
24
+ readonly _tag: "StreamRpcMethod";
25
+ readonly name: Name;
26
+ readonly req: Req;
27
+ readonly chunk: Chunk;
28
+ readonly err: Err;
29
+ }
30
+ export declare function streamRpc<const Name extends string, Req extends SchemaNoContext, Chunk extends SchemaNoContext, Err extends ErrorSchema>(name: Name, req: Req, chunk: Chunk, err: Err): StreamRpcMethod<Name, Req, Chunk, Err>;
31
+ export declare function streamRpc<const Name extends string, Req extends SchemaNoContext, Chunk extends SchemaNoContext>(name: Name, req: Req, chunk: Chunk): StreamRpcMethod<Name, Req, Chunk, NoError>;
32
+ export type AnyStreamMethod = StreamRpcMethod<string, SchemaNoContext, SchemaNoContext, ErrorSchema>;
33
+ export type StreamInput<M extends AnyStreamMethod> = S.Schema.Type<M["req"]>;
34
+ export type StreamChunk<M extends AnyStreamMethod> = S.Schema.Type<M["chunk"]>;
35
+ export type StreamError<M extends AnyStreamMethod> = S.Schema.Type<M["err"]>;
36
+ export type ExtractStreamMethod<Methods extends readonly AnyStreamMethod[], Name extends string> = Extract<Methods[number], {
37
+ readonly name: Name;
38
+ }>;
23
39
  export type AnyMethod = RpcMethod<string, SchemaNoContext, SchemaNoContext, ErrorSchema>;
24
40
  export type AnyEvent = RpcEvent<SchemaNoContext, SchemaNoContext | null, string>;
25
41
  export type RpcInput<M extends AnyMethod> = S.Schema.Type<M["req"]>;
@@ -30,12 +46,18 @@ export type RpcEventPayload<E extends AnyEvent> = S.Schema.Type<E["payload"]>;
30
46
  export type ExtractMethod<Methods extends readonly AnyMethod[], Name extends string> = Extract<Methods[number], {
31
47
  readonly name: Name;
32
48
  }>;
33
- export interface RpcContract<Methods extends ReadonlyArray<AnyMethod>, Events extends ReadonlyArray<AnyEvent>> {
49
+ export interface RpcContract<Methods extends ReadonlyArray<AnyMethod>, Events extends ReadonlyArray<AnyEvent>, StreamMethods extends ReadonlyArray<AnyStreamMethod> = readonly []> {
34
50
  readonly methods: Methods;
35
51
  readonly events: Events;
52
+ readonly streamMethods: StreamMethods;
36
53
  }
37
54
  export declare function defineContract<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>>(input: {
38
55
  readonly methods: Methods;
39
56
  readonly events: Events;
40
- }): RpcContract<Methods, Events>;
57
+ }): RpcContract<Methods, Events, readonly []>;
58
+ export declare function defineContract<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>, const StreamMethods extends ReadonlyArray<AnyStreamMethod>>(input: {
59
+ readonly methods: Methods;
60
+ readonly events: Events;
61
+ readonly streamMethods: StreamMethods;
62
+ }): RpcContract<Methods, Events, StreamMethods>;
41
63
  //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
package/dist/contract.js CHANGED
@@ -14,6 +14,9 @@ export const exitSchemaFor = (method) => S.Exit({
14
14
  failure: method.err,
15
15
  defect: S.Defect,
16
16
  });
17
+ export function streamRpc(name, req, chunk, err = NoError) {
18
+ return { _tag: "StreamRpcMethod", name, req, chunk, err };
19
+ }
17
20
  function collectDuplicates(names) {
18
21
  const counts = new Map();
19
22
  const duplicates = [];
@@ -26,15 +29,35 @@ function collectDuplicates(names) {
26
29
  }
27
30
  return duplicates;
28
31
  }
32
+ const RESERVED_STREAM_NAMES = new Set(["sf", "stream-cancel"]);
33
+ function hasReservedStreamPrefix(name) {
34
+ return name.startsWith("stream/");
35
+ }
36
+ function validateReservedNames(names, kind) {
37
+ for (const name of names) {
38
+ if (RESERVED_STREAM_NAMES.has(name)) {
39
+ throw new Error(`${kind} name "${name}" is reserved for internal stream transport.`);
40
+ }
41
+ if (hasReservedStreamPrefix(name)) {
42
+ throw new Error(`${kind} name "${name}" must not start with "stream/" (reserved for internal stream transport).`);
43
+ }
44
+ }
45
+ }
29
46
  export function defineContract(input) {
30
47
  const { methods, events } = input;
48
+ const streamMethods = input.streamMethods ?? [];
31
49
  if (!Array.isArray(methods)) {
32
50
  throw new Error("RPC contract methods must be an array.");
33
51
  }
34
52
  if (!Array.isArray(events)) {
35
53
  throw new Error("RPC contract events must be an array.");
36
54
  }
37
- const duplicateMethods = collectDuplicates(methods.map((method) => method.name));
55
+ if (!Array.isArray(streamMethods)) {
56
+ throw new Error("RPC contract streamMethods must be an array.");
57
+ }
58
+ const methodNames = methods.map((method) => method.name);
59
+ const streamMethodNames = streamMethods.map((m) => m.name);
60
+ const duplicateMethods = collectDuplicates(methodNames);
38
61
  if (duplicateMethods.length > 0) {
39
62
  throw new Error(`Duplicate RPC method name(s): ${duplicateMethods.join(", ")}`);
40
63
  }
@@ -42,5 +65,15 @@ export function defineContract(input) {
42
65
  if (duplicateEvents.length > 0) {
43
66
  throw new Error(`Duplicate RPC event name(s): ${duplicateEvents.join(", ")}`);
44
67
  }
45
- return input;
68
+ const duplicateStreamMethods = collectDuplicates(streamMethodNames);
69
+ if (duplicateStreamMethods.length > 0) {
70
+ throw new Error(`Duplicate stream method name(s): ${duplicateStreamMethods.join(", ")}`);
71
+ }
72
+ const crossDuplicates = collectDuplicates([...methodNames, ...streamMethodNames]);
73
+ if (crossDuplicates.length > 0) {
74
+ throw new Error(`Name collision between methods and streamMethods: ${crossDuplicates.join(", ")}`);
75
+ }
76
+ validateReservedNames(methodNames, "Method");
77
+ validateReservedNames(streamMethodNames, "Stream method");
78
+ return { methods, events, streamMethods };
46
79
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { createIpcKit } from "./kit.ts";
2
- export { defineContract, event, NoError, rpc } from "./contract.ts";
3
- export type { IpcBridge, IpcBridgeGlobal, IpcKit, IpcKitOptions, IpcMainHandle, } from "./kit.ts";
2
+ export { defineContract, event, NoError, rpc, streamRpc } from "./contract.ts";
3
+ export type { IpcBridge, IpcBridgeGlobal, IpcKit, IpcKitOptions, IpcMainHandle } from "./kit.ts";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpE,YAAY,EACV,SAAS,EACT,eAAe,EACf,MAAM,EACN,aAAa,EACb,aAAa,GACd,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/E,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { createIpcKit } from "./kit.js";
2
- export { defineContract, event, NoError, rpc } from "./contract.js";
2
+ export { defineContract, event, NoError, rpc, streamRpc } from "./contract.js";
package/dist/kit.d.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  import { Effect } from "effect";
2
2
  import type * as Runtime from "effect/Runtime";
3
- import type { AnyEvent, AnyMethod, RpcContract, RpcEventPayload } from "./contract.ts";
4
- import { type ChannelPrefix, type EventDecodeMode, type EventPublisherDiagnostics, type EventSubscribe, type EventSubscriber, type IpcMainLike, type Implementations, type RendererWindowLike, type RpcClient, type RpcEndpoint, type RpcEndpointDiagnostics, type RpcEventPublisher, type RpcInvoke, type RpcResponseDecodeMode } from "./types.ts";
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 } from "./types.ts";
5
5
  export type IpcBridge = {
6
6
  readonly invoke: RpcInvoke;
7
7
  readonly subscribe: EventSubscribe;
8
+ readonly onStreamFrame?: OnStreamFrame;
8
9
  };
9
10
  export type IpcBridgeGlobal<Name extends string = "api"> = {
10
11
  readonly [K in Name]: IpcBridge;
11
12
  };
12
- export type IpcKitOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[]>> = {
13
+ export type IpcKitOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>> = {
13
14
  readonly contract: C;
14
15
  readonly channelPrefix?: ChannelPrefix;
15
16
  readonly bridge?: {
@@ -20,18 +21,19 @@ export type IpcKitOptions<C extends RpcContract<readonly AnyMethod[], readonly A
20
21
  readonly events?: EventDecodeMode;
21
22
  };
22
23
  };
23
- type IpcMainOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[]>, R> = {
24
+ type IpcMainOptions<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>, R> = {
24
25
  readonly ipcMain: IpcMainLike;
25
26
  readonly handlers: Implementations<C, R>;
26
27
  readonly runtime: Runtime.Runtime<R>;
27
- readonly getWindow: () => RendererWindowLike | null;
28
+ readonly getWindows: () => ReadonlyArray<RendererWindowLike>;
28
29
  readonly maxQueueSize?: number;
30
+ readonly streamHandlers?: StreamImplementations<C, R>;
29
31
  readonly diagnostics?: {
30
32
  readonly rpc?: RpcEndpointDiagnostics;
31
33
  readonly events?: EventPublisherDiagnostics;
32
34
  };
33
35
  };
34
- export type IpcMainHandle<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[]>> = {
36
+ export type IpcMainHandle<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>> = {
35
37
  readonly endpoint: RpcEndpoint;
36
38
  readonly publisher: RpcEventPublisher<C>;
37
39
  readonly start: () => void;
@@ -44,7 +46,7 @@ export type IpcMainHandle<C extends RpcContract<readonly AnyMethod[], readonly A
44
46
  readonly dropped: number;
45
47
  };
46
48
  };
47
- export type IpcKit<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[]>> = {
49
+ export type IpcKit<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent[], readonly AnyStreamMethod[]>> = {
48
50
  readonly contract: C;
49
51
  readonly config: {
50
52
  readonly channelPrefix: ChannelPrefix;
@@ -63,8 +65,10 @@ export type IpcKit<C extends RpcContract<readonly AnyMethod[], readonly AnyEvent
63
65
  readonly renderer: (bridge: IpcBridge) => {
64
66
  readonly client: RpcClient<C>;
65
67
  readonly events: EventSubscriber<C>;
68
+ readonly streamClient: StreamRpcClient<C>;
69
+ readonly dispose: () => void;
66
70
  };
67
71
  };
68
- export declare function createIpcKit<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>>(options: IpcKitOptions<RpcContract<Methods, Events>>): IpcKit<RpcContract<Methods, Events>>;
72
+ export declare function createIpcKit<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>, const StreamMethods extends ReadonlyArray<AnyStreamMethod> = readonly []>(options: IpcKitOptions<RpcContract<Methods, Events, StreamMethods>>): IpcKit<RpcContract<Methods, Events, StreamMethods>>;
69
73
  export {};
70
74
  //# sourceMappingURL=kit.d.ts.map
package/dist/kit.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kit.d.ts","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kit.d.ts","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"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"}
package/dist/kit.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Effect } from "effect";
2
2
  import { createEventPublisher, createRpcEndpoint } from "./main.js";
3
3
  import { exposeIpcBridge, createBridgeAdapters } from "./preload.js";
4
- import { createEventSubscriber, createRpcClient } from "./renderer.js";
4
+ import { createEventSubscriber, createRpcClient, createStreamRpcClient } from "./renderer.js";
5
5
  import { defaultChannelPrefix, } from "./types.js";
6
6
  export function createIpcKit(options) {
7
7
  const contract = options.contract;
@@ -16,9 +16,10 @@ export function createIpcKit(options) {
16
16
  runtime: mainOptions.runtime,
17
17
  channelPrefix,
18
18
  diagnostics: mainOptions.diagnostics?.rpc,
19
+ streamHandlers: mainOptions.streamHandlers,
19
20
  });
20
21
  const publisher = createEventPublisher(contract, {
21
- getWindow: mainOptions.getWindow,
22
+ getWindows: mainOptions.getWindows,
22
23
  maxQueueSize: mainOptions.maxQueueSize,
23
24
  channelPrefix,
24
25
  diagnostics: mainOptions.diagnostics?.events,
@@ -108,6 +109,19 @@ export function createIpcKit(options) {
108
109
  };
109
110
  };
110
111
  const renderer = (bridge) => {
112
+ const hasStreamMethods = (contract.streamMethods?.length ?? 0) > 0;
113
+ if (hasStreamMethods && !bridge.onStreamFrame) {
114
+ throw new Error("Contract defines stream methods but bridge.onStreamFrame is missing. " +
115
+ "Ensure the preload bridge exposes onStreamFrame.");
116
+ }
117
+ let streamHandle = null;
118
+ if (hasStreamMethods && bridge.onStreamFrame) {
119
+ streamHandle = createStreamRpcClient(contract, {
120
+ invoke: bridge.invoke,
121
+ onStreamFrame: bridge.onStreamFrame,
122
+ });
123
+ }
124
+ const emptyStreamClient = Object.create(null);
111
125
  return {
112
126
  client: createRpcClient(contract, {
113
127
  invoke: bridge.invoke,
@@ -117,6 +131,10 @@ export function createIpcKit(options) {
117
131
  subscribe: bridge.subscribe,
118
132
  decodeMode: eventDecodeMode,
119
133
  }),
134
+ streamClient: streamHandle?.client ?? emptyStreamClient,
135
+ dispose: () => {
136
+ streamHandle?.dispose();
137
+ },
120
138
  };
121
139
  };
122
140
  return {
package/dist/main.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { RpcContract } from "./contract.ts";
1
+ import type { AnyStreamMethod, RpcContract } from "./contract.ts";
2
2
  import { type AnyEvent, type AnyMethod, type EventPublisherOptions, type Implementations, type IpcMainLike, type RpcEndpoint, type RpcEndpointOptions, type RpcEventPublisher } from "./types.ts";
3
- export declare function createRpcEndpoint<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>, R = never>(contract: RpcContract<Methods, Events>, ipc: IpcMainLike, implementations: Implementations<RpcContract<Methods, Events>, R>, options: RpcEndpointOptions<R>): RpcEndpoint;
4
- export declare function createEventPublisher<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>>(_contract: RpcContract<Methods, Events>, options: EventPublisherOptions): RpcEventPublisher<RpcContract<Methods, Events>>;
3
+ export declare function createRpcEndpoint<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>, const StreamMethods extends ReadonlyArray<AnyStreamMethod> = readonly [], R = never>(contract: RpcContract<Methods, Events, StreamMethods>, ipc: IpcMainLike, implementations: Implementations<RpcContract<Methods, Events, StreamMethods>, R>, options: RpcEndpointOptions<RpcContract<Methods, Events, StreamMethods>, R>): RpcEndpoint;
4
+ export declare function createEventPublisher<const Methods extends ReadonlyArray<AnyMethod>, const Events extends ReadonlyArray<AnyEvent>, const StreamMethods extends ReadonlyArray<AnyStreamMethod> = readonly []>(_contract: RpcContract<Methods, Events, StreamMethods>, options: EventPublisherOptions): RpcEventPublisher<RpcContract<Methods, Events, StreamMethods>>;
5
5
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,eAAe,CAAC;AAQvB,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,EACvB,MAAM,YAAY,CAAC;AAmBpB,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAC5C,CAAC,GAAG,KAAK,EAET,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EACtC,GAAG,EAAE,WAAW,EAChB,eAAe,EAAE,eAAe,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EACjE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,WAAW,CAgNb;AAmBD,wBAAgB,oBAAoB,CAClC,KAAK,CAAC,OAAO,SAAS,aAAa,CAAC,SAAS,CAAC,EAC9C,KAAK,CAAC,MAAM,SAAS,aAAa,CAAC,QAAQ,CAAC,EAE5C,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,EACvC,OAAO,EAAE,qBAAqB,GAC7B,iBAAiB,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAkMjD"}
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"}