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/CHANGELOG.md ADDED
@@ -0,0 +1,90 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.10.0 - 2026-08-15
6
+
7
+ ### Breaking
8
+
9
+ - The package now requires Effect v4 (`effect@^4.0.0-rc.109`). Effect v3 is no
10
+ longer supported.
11
+ - `RpcEndpointOptions.runtime` and `ipc.main({ runtime })` were replaced by
12
+ `context`, which accepts a v4 `Context.Context<R>`. Use `Context.empty()` when
13
+ handlers require no application services.
14
+ - Renderer streams now use Effect v4's `Stream.callback` and `Queue` APIs.
15
+ - Cause extraction, fiber interruption, legacy `Exit` codecs, and schema
16
+ constraints were migrated to their Effect v4 equivalents.
17
+ - `event()` no longer accepts a third `context` schema argument. It was never
18
+ read by the publisher or subscriber; remove it from any `event(...)` calls.
19
+ - `channelPrefix.rpc` and `channelPrefix.event` must now differ; identical
20
+ prefixes throw at construction time.
21
+ - Providing `streamHandlers` when the contract defines no `streamMethods` now
22
+ throws instead of being silently ignored.
23
+ - Methods whose request schema type is `object` (e.g. `S.ObjectKeyword`) now require
24
+ an argument at the call site; previously the client generated a zero-arg
25
+ caller that always sent `{}`.
26
+
27
+ ### Added
28
+
29
+ - Handlers (unary and stream) receive an optional second `context` argument:
30
+ `{ sender: WebContentsLike | null }`.
31
+ - `EventSubscriber.stream(event)` — Effect-native event consumption as a
32
+ `Stream` that unsubscribes when its scope closes.
33
+ - `ipc.renderer(bridge, { diagnostics })` — renderer-side diagnostics hooks for
34
+ RPC, events, and streams in kit mode.
35
+ - `assertValidChannelPrefix` exported from `electron-effect-rpc/types`.
36
+ - Named structured-clone transport types (`IpcEncodedValue`,
37
+ `IpcEncodedRecord`, and `DiagnosticCause`) exported from
38
+ `electron-effect-rpc/types`.
39
+
40
+ ### Fixed
41
+
42
+ - Main-side stream fibers no longer leak when the renderer goes away without
43
+ cancelling: a destroyed sender now terminates the pipeline on the next chunk,
44
+ and when the real Electron `WebContents` emitter is available the fiber is
45
+ interrupted immediately on `destroyed`.
46
+ - Normally-completed streams no longer send a redundant `stream-cancel` invoke.
47
+ - `isNoErrorSchema` now matches `Never` schemas by AST tag, so a duplicated
48
+ schema package instance can't silently turn typed failures into defects.
49
+ - Stream failure-encoding defects now carry the encoding error message instead
50
+ of `[object Object]`.
51
+ - Preload bindings now accept the real Electron module without casts, preserve
52
+ Electron method receivers, and report a descriptive error when synchronous
53
+ loading is unavailable in ESM.
54
+ - Protocol envelopes and stream frames preserve structured-clone payloads such
55
+ as `bigint`, maps, sets, binary values, and cyclic object graphs while leaving
56
+ domain validation to each contract schema.
57
+
58
+ ## 0.8.0 and earlier
59
+
60
+ `getWindow` was renamed to `getWindows` and now returns an array, enabling
61
+ multi-window event fan-out. Empty array replaces `null` for "no windows."
62
+
63
+ Before:
64
+
65
+ ```ts
66
+ getWindow: () => mainWindow,
67
+ ```
68
+
69
+ After:
70
+
71
+ ```ts
72
+ getWindows: () => [mainWindow],
73
+ ```
74
+
75
+ Renderer RPC methods now return `Effect.Effect` instead of `Promise`, and
76
+ `IpcMainHandle.emit` was removed in favor of `publish`.
77
+
78
+ Before:
79
+
80
+ ```ts
81
+ const result = await client.GetAppVersion();
82
+ await mainRpc.emit(WorkUnitProgress, payload);
83
+ ```
84
+
85
+ After:
86
+
87
+ ```ts
88
+ const result = await Effect.runPromise(client.GetAppVersion());
89
+ await Effect.runPromise(mainRpc.publish(WorkUnitProgress, payload));
90
+ ```
package/README.md CHANGED
@@ -1,35 +1,43 @@
1
1
  # electron-effect-rpc
2
2
 
3
- Typed IPC RPC for Electron, built on Effect and @effect/schema.
3
+ [![npm](https://img.shields.io/npm/v/electron-effect-rpc)](https://www.npmjs.com/package/electron-effect-rpc)
4
4
 
5
- The ergonomic default is now a single shared `createIpcKit` configuration that
6
- you reuse in main, preload, and renderer code. Low-level subpath APIs still
7
- exist and remain fully supported.
5
+ Typed, schema-validated IPC for Electron, built on [Effect](https://effect.website).
6
+
7
+ Define your IPC surface once — methods, events, and streams, each described
8
+ with `effect/Schema` — and get a fully typed client in the renderer, fully
9
+ typed handlers in main, and runtime validation at every process boundary. No
10
+ hand-rolled channel strings, no `any`-typed `invoke` calls, no drift between
11
+ processes.
12
+
13
+ The primary API is a single shared `createIpcKit` configuration reused across
14
+ main, preload, and renderer. Low-level per-piece factories remain available as
15
+ subpath imports.
8
16
 
9
17
  This package is ESM-only. It targets modern Electron runtimes and assumes an
10
18
  ESM-capable build pipeline.
11
19
 
12
20
  ## Features
13
21
 
14
- - Single shared contract for methods, events, and streaming RPC.
15
- - Single shared kit config to eliminate cross-process prefix drift.
16
- - End-to-end schema validation at IPC boundaries.
17
- - Effect-first renderer RPC with typed domain and defect channels.
18
- - Streaming RPC: handlers return `Stream.Stream`, clients consume `Stream.Stream`.
19
- - Effect-native main handlers with explicit runtime injection.
20
- - Explicit lifecycle handles and bounded event queue backpressure.
22
+ - One contract for methods, events, and streaming RPC, shared by all three processes.
23
+ - One kit config, so channel naming can never drift between processes.
24
+ - Schema validation on every IPC crossing, in both directions.
25
+ - Typed domain errors in the Effect error channel; transport problems as `RpcDefectError` with stable codes.
26
+ - Streaming RPC: handlers return `Stream.Stream`, clients consume `Stream.Stream`, cancellation propagates.
27
+ - Main handlers are Effects, run with an injected `Context` (so your services are available).
28
+ - Explicit lifecycle handles (`start`/`stop`/`dispose`) and bounded event queue backpressure.
21
29
  - Structured diagnostics hooks for decode/protocol/dispatch failures.
22
30
 
23
31
  ## Requirements
24
32
 
25
- - Electron with context isolation enabled.
33
+ - Electron >= 28 with context isolation enabled.
26
34
  - ESM-capable bundling.
27
- - Peer dependencies: `effect`, `@effect/schema`, `electron`.
35
+ - Peer dependencies: `effect` (`^4.0.0-rc.109`), `electron`.
28
36
 
29
37
  ## Installation
30
38
 
31
39
  ```sh
32
- bun add electron-effect-rpc effect @effect/schema
40
+ bun add electron-effect-rpc effect
33
41
  ```
34
42
 
35
43
  ## Quickstart (Kit-First)
@@ -37,7 +45,7 @@ bun add electron-effect-rpc effect @effect/schema
37
45
  ### 1) Define contract and kit once
38
46
 
39
47
  ```ts
40
- import * as S from "@effect/schema/Schema";
48
+ import * as S from "effect/Schema";
41
49
  import { createIpcKit, defineContract, event, rpc, streamRpc } from "electron-effect-rpc";
42
50
 
43
51
  export const GetAppVersion = rpc("GetAppVersion", S.Struct({}), S.Struct({ version: S.String }));
@@ -63,36 +71,51 @@ const contract = defineContract({
63
71
  streamMethods: [StreamAiGeneration] as const,
64
72
  });
65
73
 
74
+ export const ipc = createIpcKit({ contract });
75
+ ```
76
+
77
+ `createIpcKit` accepts optional configuration; the values below are the
78
+ defaults, so only set them to deviate:
79
+
80
+ ```ts
66
81
  export const ipc = createIpcKit({
67
82
  contract,
68
83
  channelPrefix: { rpc: "rpc/", event: "event/" },
69
84
  bridge: { global: "api" },
70
85
  decode: { rpc: "envelope", events: "safe" },
86
+ streamBuffer: { bufferSize: "unbounded" },
71
87
  });
72
88
  ```
73
89
 
74
90
  ### 2) Main process
75
91
 
76
92
  ```ts
77
- import { app, ipcMain } from "electron";
78
- import { Effect, Stream } from "effect";
79
- import * as Runtime from "effect/Runtime";
93
+ import path from "node:path";
94
+ import { app, BrowserWindow, ipcMain } from "electron";
95
+ import { Context, Effect, Stream } from "effect";
80
96
  import { ipc, WorkUnitProgress } from "./shared-ipc.ts";
81
97
 
98
+ const mainWindow = new BrowserWindow({
99
+ webPreferences: { preload: path.join(import.meta.dirname, "preload.js") },
100
+ });
101
+
82
102
  const mainRpc = ipc.main({
83
103
  ipcMain,
84
104
  handlers: {
85
105
  GetAppVersion: () => Effect.succeed({ version: app.getVersion() }),
106
+ // Handlers may take an optional second argument with request context:
107
+ // GetAppVersion: (_input, { sender }) => ...
86
108
  },
87
109
  streamHandlers: {
88
110
  StreamAiGeneration: ({ prompt }) =>
89
111
  Stream.fromIterable(prompt.split(" ")).pipe(Stream.map((word) => ({ delta: word + " " }))),
90
112
  },
91
- runtime: Runtime.defaultRuntime,
113
+ context: Context.empty(),
92
114
  getWindows: () => [mainWindow],
93
115
  });
94
116
 
95
117
  mainRpc.start();
118
+ app.on("will-quit", () => mainRpc.dispose());
96
119
 
97
120
  void Effect.runPromise(
98
121
  mainRpc.publish(WorkUnitProgress, {
@@ -145,82 +168,132 @@ const unsubscribe = events.subscribe(WorkUnitProgress, (payload) => {
145
168
  console.log(payload.chunk);
146
169
  });
147
170
 
171
+ // Or consume events as an Effect Stream (unsubscribes when the scope closes):
172
+ await Effect.runPromise(
173
+ events
174
+ .stream(WorkUnitProgress)
175
+ .pipe(Stream.runForEach((payload) => Effect.sync(() => console.log(payload.chunk)))),
176
+ );
177
+
148
178
  // later
149
179
  unsubscribe();
150
180
  dispose();
151
181
  ```
152
182
 
153
- ### 5) Window typing
183
+ Renderer-side diagnostics hooks are available through the second argument:
154
184
 
155
185
  ```ts
156
- declare global {
157
- interface Window {
158
- api: {
159
- invoke: (method: string, payload: unknown) => Promise<unknown>;
160
- subscribe: (name: string, handler: (payload: unknown) => void) => () => void;
161
- onStreamFrame?: (listener: (frame: unknown) => void) => () => void;
162
- };
163
- }
164
- }
186
+ const renderer = ipc.renderer(window.api, {
187
+ diagnostics: {
188
+ rpc: { onDecodeFailure: (ctx) => console.warn("rpc decode failure", ctx) },
189
+ events: { onDecodeFailure: (ctx) => console.warn("event decode failure", ctx) },
190
+ },
191
+ });
165
192
  ```
166
193
 
167
- ## Error Model
168
-
169
- Domain failures are modeled with tagged error schemas and are surfaced in the
170
- Effect error channel as those same tagged values. Unexpected failures,
171
- transport defects, and protocol mismatches are surfaced as `RpcDefectError`,
172
- which includes a stable `code` discriminator:
173
- `request_encoding_failed`, `invoke_failed`,
174
- `success_payload_decoding_failed`, `failure_payload_decoding_failed`,
175
- `noerror_contract_violation`, `invalid_response_envelope`,
176
- `legacy_decode_failed`, `remote_defect`,
177
- `stream_invoke_failed`, `stream_handshake_invalid`,
178
- `stream_chunk_decode_failed`, and `stream_error_decode_failed`.
179
-
180
- ## Breaking Changes
181
-
182
- `getWindow` was renamed to `getWindows` and now returns an array, enabling
183
- multi-window event fan-out. Empty array replaces `null` for "no windows."
194
+ ### 5) Window typing
184
195
 
185
- Before:
196
+ Use the exported `IpcBridgeGlobal` helper so the declared shape stays in sync
197
+ with what `ipc.preload()` exposes:
186
198
 
187
199
  ```ts
188
- getWindow: () => mainWindow,
189
- ```
190
-
191
- After:
200
+ import type { IpcBridgeGlobal } from "electron-effect-rpc";
192
201
 
193
- ```ts
194
- getWindows: () => [mainWindow],
202
+ declare global {
203
+ interface Window extends IpcBridgeGlobal {}
204
+ }
195
205
  ```
196
206
 
197
- Renderer RPC methods now return `Effect.Effect` instead of `Promise`, and
198
- `IpcMainHandle.emit` was removed in favor of `publish`.
207
+ For a custom global name, use `IpcBridgeGlobal<"myBridge">`.
199
208
 
200
- Before:
209
+ ## Error Model
201
210
 
202
- ```ts
203
- const result = await client.GetAppVersion();
204
- await mainRpc.emit(WorkUnitProgress, payload);
205
- ```
211
+ A call site sees exactly two kinds of failure in the Effect error channel:
206
212
 
207
- After:
213
+ - **Domain failures** — the tagged errors you declared in the contract's error
214
+ schema, decoded back into those same tagged values.
215
+ - **`RpcDefectError`** — everything else: transport problems, schema
216
+ mismatches, and unexpected main-process exceptions. It is itself tagged
217
+ (`_tag: "RpcDefectError"`) and carries a stable `code` discriminator.
208
218
 
209
219
  ```ts
210
- const result = await Effect.runPromise(client.GetAppVersion());
211
- await Effect.runPromise(mainRpc.publish(WorkUnitProgress, payload));
220
+ import { Effect } from "effect";
221
+
222
+ const result = await Effect.runPromise(
223
+ client.DeleteWorkspace({ id }).pipe(
224
+ // a tagged error you declared in the contract
225
+ Effect.catchTag("AccessDeniedError", (e) =>
226
+ Effect.succeed({ deleted: false, reason: e.message }),
227
+ ),
228
+ // transport/contract problems
229
+ Effect.catchTag("RpcDefectError", (defect) =>
230
+ Effect.sync(() => log.error(defect.code, defect.message)).pipe(
231
+ Effect.andThen(Effect.fail(defect)),
232
+ ),
233
+ ),
234
+ ),
235
+ );
212
236
  ```
213
237
 
238
+ `RpcDefectError.code` values:
239
+
240
+ | Code | Meaning |
241
+ | --------------------------------- | ------------------------------------------------------------------- |
242
+ | `request_encoding_failed` | Request payload failed schema encoding before leaving the renderer. |
243
+ | `invoke_failed` | The underlying `ipcRenderer.invoke` rejected (transport failure). |
244
+ | `success_payload_decoding_failed` | Main's success payload failed response schema decoding. |
245
+ | `failure_payload_decoding_failed` | Main's typed failure payload failed error schema decoding. |
246
+ | `noerror_contract_violation` | A failure arrived for a method that declares `NoError`. |
247
+ | `invalid_response_envelope` | The response was not a valid envelope. |
248
+ | `legacy_decode_failed` | `dual` decode mode could not parse a legacy `Exit` payload. |
249
+ | `remote_defect` | The main-side handler died, threw, or was interrupted. |
250
+ | `stream_invoke_failed` | The stream handshake invoke rejected (transport failure). |
251
+ | `stream_handshake_invalid` | The stream handshake response had an unexpected shape. |
252
+ | `stream_chunk_decode_failed` | A stream chunk failed schema decoding. |
253
+ | `stream_error_decode_failed` | A stream's typed error frame failed schema decoding. |
254
+
255
+ Defect envelopes carry the main-process error message verbatim across IPC. If
256
+ any window in your app loads remote or less-trusted content, treat that as
257
+ information disclosure: catch and sanitize errors in your handlers rather than
258
+ letting raw exceptions (paths, query fragments) become defects.
259
+
260
+ ## Operational Notes
261
+
262
+ **Stream backpressure.** Stream frames are pushed from main as fast as the
263
+ handler produces them; there is no acknowledgment across the IPC boundary. The
264
+ renderer buffers with `bufferSize: "unbounded"` by default, which is lossless
265
+ but means a fast producer with a slow consumer grows renderer memory. Bounded
266
+ buffers (`dropping`/`sliding`) are lossy by design, while completion and failure
267
+ signals remain reliable through Effect v4's `Stream.callback` queue. Rate-limit
268
+ fast producers in the handler (`Stream.throttle`, batching) rather than relying
269
+ on a bounded renderer buffer.
270
+
271
+ **Unary RPC cancellation.** Interrupting the renderer-side Effect of a
272
+ client call (e.g. via `Effect.timeout`) does not abort the main-side handler;
273
+ the underlying `ipcRenderer.invoke` is not abortable. The handler runs to
274
+ completion and its response is discarded. Streaming RPC does propagate
275
+ cancellation to main. If a unary handler does expensive work, model it as a
276
+ stream or build explicit cancellation into your contract.
277
+
278
+ **Renderer teardown.** Main interrupts a stream's fiber when the renderer's
279
+ `webContents` is destroyed (immediately when the real Electron `WebContents`
280
+ event emitter is available, otherwise on the next chunk), so handler fibers do
281
+ not outlive closed windows.
282
+
283
+ ## Migration Notes
284
+
285
+ See [CHANGELOG.md](./CHANGELOG.md) for breaking changes between versions.
286
+
214
287
  ## Low-Level APIs (Still Supported)
215
288
 
216
289
  If you need direct control, keep using subpath entry points:
217
290
 
218
- - `electron-effect-rpc/contract`
219
- - `electron-effect-rpc/main`
220
- - `electron-effect-rpc/renderer`
221
- - `electron-effect-rpc/preload`
222
- - `electron-effect-rpc/types`
223
- - `electron-effect-rpc/testing`
291
+ - `electron-effect-rpc/contract` — `rpc`, `event`, `streamRpc`, `defineContract`
292
+ - `electron-effect-rpc/main` — `createRpcEndpoint`, `createEventPublisher`
293
+ - `electron-effect-rpc/renderer` — `createRpcClient`, `createEventSubscriber`, `createStreamRpcClient`
294
+ - `electron-effect-rpc/preload` — `exposeIpcBridge`, `createBridgeAdapters`
295
+ - `electron-effect-rpc/types` — shared types, `RpcDefectError`, `assertValidChannelPrefix`
296
+ - `electron-effect-rpc/testing` — `createInvokeStub`, `createDeferred` for unit-testing clients without Electron
224
297
 
225
298
  ## Root API Surface
226
299
 
@@ -232,7 +305,7 @@ The root entry point exports:
232
305
 
233
306
  Low-level factories like `createRpcClient` remain subpath-only by design.
234
307
 
235
- ## Tutorials
308
+ ## Documentation
236
309
 
237
310
  For deeper walkthroughs and production guidance:
238
311
 
@@ -241,8 +314,9 @@ For deeper walkthroughs and production guidance:
241
314
  - [Typed Errors, Defects, and Diagnostics](./docs/tutorials/02-typed-errors-defects-diagnostics.md)
242
315
  - [Events, Lifecycle, and Backpressure](./docs/tutorials/03-events-lifecycle-backpressure.md)
243
316
  - [Streaming RPC](./docs/tutorials/04-streaming-rpc.md)
317
+ - [Architecture overview](./docs/architecture.md) and [ADRs](./docs/adr/) for design rationale.
244
318
 
245
- ## Conventions
319
+ ## Repository Conventions
246
320
 
247
321
  - Relative imports use `.ts` extensions.
248
322
  - Package imports are extensionless.
@@ -0,0 +1,17 @@
1
+ /** Values supported by Electron's structured-clone IPC transport. */
2
+ export type IpcEncodedValue = string | number | bigint | boolean | null | undefined | Date | RegExp | Error | ArrayBuffer | SharedArrayBuffer | ArrayBufferView | ReadonlyArray<IpcEncodedValue> | ReadonlyMap<IpcEncodedValue, IpcEncodedValue> | ReadonlySet<IpcEncodedValue> | IpcEncodedRecord;
3
+ export type IpcEncodedRecord = {
4
+ readonly [key: string]: IpcEncodedValue;
5
+ };
6
+ /** True for non-null, non-array objects. Arrays are not IPC records. */
7
+ export declare function isRecord<T>(value: T): value is T & IpcEncodedRecord;
8
+ export declare function isIpcEncodedValue<T>(value: T): value is T & IpcEncodedValue;
9
+ export declare function isStringValue<T>(value: T): value is T & string;
10
+ export declare function isNumberValue<T>(value: T): value is T & number;
11
+ export declare function isFunctionValue<T>(value: T): boolean;
12
+ export declare function formatUnknown<T>(value: T): string;
13
+ export declare function parseIpcEncodedValue<T>(value: T): IpcEncodedValue | null;
14
+ /** Values reported through diagnostics after transport-safe normalization. */
15
+ export type DiagnosticCause = IpcEncodedValue;
16
+ export declare function toDiagnosticCause<T>(value: T): DiagnosticCause;
17
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,IAAI,GACJ,MAAM,GACN,KAAK,GACL,WAAW,GACX,iBAAiB,GACjB,eAAe,GACf,aAAa,CAAC,eAAe,CAAC,GAC9B,WAAW,CAAC,eAAe,EAAE,eAAe,CAAC,GAC7C,WAAW,CAAC,eAAe,CAAC,GAC5B,gBAAgB,CAAC;AAErB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CACzC,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,gBAAgB,CAEnE;AA4ED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,eAAe,CAE3E;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,MAAM,CAE9D;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,MAAM,CAE9D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAEpD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,eAAe,GAAG,IAAI,CAExE;AAED,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC;AAE9C,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,eAAe,CAM9D"}
@@ -0,0 +1,89 @@
1
+ import * as Predicate from "effect/Predicate";
2
+ /** True for non-null, non-array objects. Arrays are not IPC records. */
3
+ export function isRecord(value) {
4
+ return Predicate.isObject(value);
5
+ }
6
+ function isPrimitiveIpcValue(value) {
7
+ return (Predicate.isString(value) ||
8
+ Predicate.isNumber(value) ||
9
+ Predicate.isBigInt(value) ||
10
+ Predicate.isBoolean(value) ||
11
+ value === null ||
12
+ value === undefined);
13
+ }
14
+ function isIpcEncodedValueInternal(value, visited) {
15
+ if (isPrimitiveIpcValue(value)) {
16
+ return true;
17
+ }
18
+ if (!Predicate.isObjectOrArray(value)) {
19
+ return false;
20
+ }
21
+ if (value instanceof Date ||
22
+ value instanceof RegExp ||
23
+ value instanceof Error ||
24
+ value instanceof ArrayBuffer ||
25
+ value instanceof SharedArrayBuffer ||
26
+ ArrayBuffer.isView(value)) {
27
+ return true;
28
+ }
29
+ if (value instanceof Promise || value instanceof WeakMap || value instanceof WeakSet) {
30
+ return false;
31
+ }
32
+ if (visited.has(value)) {
33
+ return true;
34
+ }
35
+ visited.add(value);
36
+ if (Array.isArray(value)) {
37
+ return value.every((item) => isIpcEncodedValueInternal(item, visited));
38
+ }
39
+ if (value instanceof Map) {
40
+ for (const [key, item] of value) {
41
+ if (!isIpcEncodedValueInternal(key, visited) || !isIpcEncodedValueInternal(item, visited)) {
42
+ return false;
43
+ }
44
+ }
45
+ return true;
46
+ }
47
+ if (value instanceof Set) {
48
+ for (const item of value) {
49
+ if (!isIpcEncodedValueInternal(item, visited)) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ }
55
+ if (!isRecord(value)) {
56
+ return false;
57
+ }
58
+ for (const key of Object.keys(value)) {
59
+ if (!isIpcEncodedValueInternal(value[key], visited)) {
60
+ return false;
61
+ }
62
+ }
63
+ return true;
64
+ }
65
+ export function isIpcEncodedValue(value) {
66
+ return isIpcEncodedValueInternal(value, new WeakSet());
67
+ }
68
+ export function isStringValue(value) {
69
+ return Predicate.isString(value);
70
+ }
71
+ export function isNumberValue(value) {
72
+ return Predicate.isNumber(value);
73
+ }
74
+ export function isFunctionValue(value) {
75
+ return Predicate.isFunction(value);
76
+ }
77
+ export function formatUnknown(value) {
78
+ return value instanceof Error ? value.message : String(value);
79
+ }
80
+ export function parseIpcEncodedValue(value) {
81
+ return isIpcEncodedValue(value) ? value : null;
82
+ }
83
+ export function toDiagnosticCause(value) {
84
+ if (value instanceof Error) {
85
+ return value;
86
+ }
87
+ const parsed = parseIpcEncodedValue(value);
88
+ return parsed !== null ? parsed : formatUnknown(value);
89
+ }
@@ -1,6 +1,6 @@
1
- import * as S from "@effect/schema/Schema";
2
- export type SchemaNoContext = S.Schema.AnyNoContext;
3
- export declare const NoError: typeof S.Never;
1
+ import * as S from "effect/Schema";
2
+ export type SchemaNoContext = S.Codec<any, any, never, never>;
3
+ export declare const NoError: S.Never;
4
4
  export type NoError = typeof NoError;
5
5
  export type ErrorSchema = SchemaNoContext | NoError;
6
6
  export declare function isNoErrorSchema(schema: ErrorSchema): schema is NoError;
@@ -12,14 +12,12 @@ export interface RpcMethod<Name extends string, Req extends SchemaNoContext, Res
12
12
  }
13
13
  export declare function rpc<const Name extends string, Req extends SchemaNoContext, Res extends SchemaNoContext, Err extends ErrorSchema>(name: Name, req: Req, res: Res, err: Err): RpcMethod<Name, Req, Res, Err>;
14
14
  export declare function rpc<const Name extends string, Req extends SchemaNoContext, Res extends SchemaNoContext>(name: Name, req: Req, res: Res): RpcMethod<Name, Req, Res, NoError>;
15
- export interface RpcEvent<Payload extends SchemaNoContext, Context extends SchemaNoContext | null, Name extends string = string> {
15
+ export interface RpcEvent<Payload extends SchemaNoContext, Name extends string = string> {
16
16
  readonly name: Name;
17
17
  readonly payload: Payload;
18
- readonly context: Context;
19
18
  }
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
- export declare function event<const Name extends string, Payload extends SchemaNoContext>(name: Name, payload: Payload): RpcEvent<Payload, null, Name>;
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>;
19
+ export declare function event<const Name extends string, Payload extends SchemaNoContext>(name: Name, payload: Payload): RpcEvent<Payload, Name>;
20
+ export declare const exitSchemaFor: <Name extends string, Req extends SchemaNoContext, Res extends SchemaNoContext, Err extends ErrorSchema>(method: RpcMethod<Name, Req, Res, Err>) => S.toCodecJson<S.Exit<Res, Err, S.Defect>>;
23
21
  export interface StreamRpcMethod<Name extends string, Req extends SchemaNoContext, Chunk extends SchemaNoContext, Err extends ErrorSchema = NoError> {
24
22
  readonly _tag: "StreamRpcMethod";
25
23
  readonly name: Name;
@@ -37,7 +35,7 @@ export type ExtractStreamMethod<Methods extends readonly AnyStreamMethod[], Name
37
35
  readonly name: Name;
38
36
  }>;
39
37
  export type AnyMethod = RpcMethod<string, SchemaNoContext, SchemaNoContext, ErrorSchema>;
40
- export type AnyEvent = RpcEvent<SchemaNoContext, SchemaNoContext | null, string>;
38
+ export type AnyEvent = RpcEvent<SchemaNoContext, string>;
41
39
  export type RpcInput<M extends AnyMethod> = S.Schema.Type<M["req"]>;
42
40
  export type RpcOutput<M extends AnyMethod> = S.Schema.Type<M["res"]>;
43
41
  export type RpcError<M extends AnyMethod> = S.Schema.Type<M["err"]>;
@@ -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
@@ -1,19 +1,18 @@
1
- import * as S from "@effect/schema/Schema";
1
+ import * as S from "effect/Schema";
2
+ import * as SchemaAST from "effect/SchemaAST";
2
3
  export const NoError = S.Never;
3
4
  export function isNoErrorSchema(schema) {
4
- return schema === NoError;
5
+ // Also match by AST tag so a Never schema from a second copy of the
6
+ // schema package (npm dedup failure) is still treated as NoError.
7
+ return schema === NoError || SchemaAST.isNever(schema.ast);
5
8
  }
6
9
  export function rpc(name, req, res, err = NoError) {
7
10
  return { name, req, res, err };
8
11
  }
9
- export function event(name, payload, context) {
10
- return { name, payload, context: context ?? null };
12
+ export function event(name, payload) {
13
+ return { name, payload };
11
14
  }
12
- export const exitSchemaFor = (method) => S.Exit({
13
- success: method.res,
14
- failure: method.err,
15
- defect: S.Defect,
16
- });
15
+ export const exitSchemaFor = (method) => S.toCodecJson(S.Exit(method.res, method.err, S.Defect()));
17
16
  export function streamRpc(name, req, chunk, err = NoError) {
18
17
  return { _tag: "StreamRpcMethod", name, req, chunk, err };
19
18
  }
@@ -61,7 +60,7 @@ export function defineContract(input) {
61
60
  if (duplicateMethods.length > 0) {
62
61
  throw new Error(`Duplicate RPC method name(s): ${duplicateMethods.join(", ")}`);
63
62
  }
64
- const duplicateEvents = collectDuplicates(events.map((event) => event.name));
63
+ const duplicateEvents = collectDuplicates(events.map((rpcEvent) => rpcEvent.name));
65
64
  if (duplicateEvents.length > 0) {
66
65
  throw new Error(`Duplicate RPC event name(s): ${duplicateEvents.join(", ")}`);
67
66
  }