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 +69 -20
- package/dist/contract.d.ts +24 -2
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +35 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/kit.d.ts +12 -8
- package/dist/kit.d.ts.map +1 -1
- package/dist/kit.js +20 -2
- package/dist/main.d.ts +3 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +230 -24
- package/dist/preload.d.ts +1 -0
- package/dist/preload.d.ts.map +1 -1
- package/dist/preload.js +29 -7
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +43 -1
- package/dist/renderer.d.ts +5 -4
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +161 -9
- package/dist/types.d.ts +37 -15
- package/dist/types.d.ts.map +1 -1
- package/package.json +29 -23
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
|
-
|
|
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
|
-
|
|
92
|
+
getWindows: () => [mainWindow],
|
|
80
93
|
});
|
|
81
94
|
|
|
82
95
|
mainRpc.start();
|
|
83
96
|
|
|
84
|
-
void Effect.runPromise(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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`,
|
|
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
|
package/dist/contract.d.ts
CHANGED
|
@@ -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
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,uBAAuB,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;AAEpD,eAAO,MAAM,OAAO,gBAAU,CAAC;AAC/B,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,OAAO,CAAC;AAEpD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,IAAI,OAAO,CAEtE;AAED,MAAM,WAAW,SAAS,CACxB,IAAI,SAAS,MAAM,EACnB,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,WAAW,GAAG,OAAO;IAEjC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB;AAED,wBAAgB,GAAG,CACjB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,WAAW,EACvB,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE5E,wBAAgB,GAAG,CACjB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,eAAe,EAC3B,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AAWtE,MAAM,WAAW,QAAQ,CACvB,OAAO,SAAS,eAAe,EAC/B,OAAO,SAAS,eAAe,GAAG,IAAI,EACtC,IAAI,SAAS,MAAM,GAAG,MAAM;IAE5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,KAAK,CACnB,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,OAAO,SAAS,eAAe,EAC/B,OAAO,SAAS,eAAe,EAC/B,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAEpF,wBAAgB,KAAK,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,SAAS,eAAe,EAC9E,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,GACf,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAUjC,eAAO,MAAM,aAAa,GACxB,IAAI,SAAS,MAAM,EACnB,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,WAAW,EAEvB,QAAQ,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,+BAMpC,CAAC;AAEL,MAAM,MAAM,SAAS,GAAG,SAAS,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
|
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":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,
|
|
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
|
-
|
|
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
|
|
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
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"
|
|
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"}
|