Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the WalkthroughThis change introduces a comprehensive Electron IPC adapter for the oRPC framework, enabling seamless RPC communication between Electron's main and renderer processes. It includes new client and server-side adapter modules, supporting TypeScript types, and detailed documentation. Additionally, a fully functional Electron playground application is added, complete with middleware, routing, schemas, React components, and build configurations. Documentation and configuration files are updated to reflect these new features and integrations. Changes
Sequence Diagram(s)sequenceDiagram
participant Renderer as Renderer Process
participant Preload as Preload Script
participant Main as Main Process
participant oRPC as oRPC Handler
Renderer->>Preload: Calls exposed oRPC API (via window.api)
Preload->>Main: Sends IPC message (request)
Main->>oRPC: Passes request to oRPC handler
oRPC-->>Main: Returns response
Main->>Preload: Sends IPC message (response)
Preload->>Renderer: Delivers response to client code
Poem
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
More templates
@orpc/arktype
@orpc/client
@orpc/nest
@orpc/contract
@orpc/openapi
@orpc/openapi-client
@orpc/react-query
@orpc/react
@orpc/server
@orpc/shared
@orpc/solid-query
@orpc/standard-server
@orpc/standard-server-fetch
@orpc/standard-server-node
@orpc/standard-server-peer
@orpc/svelte-query
@orpc/valibot
@orpc/vue-colada
@orpc/vue-query
@orpc/zod
commit: |
There was a problem hiding this comment.
Actionable comments posted: 38
🧹 Nitpick comments (55)
eslint.config.js (1)
57-62: Expand rule disable to cover Electron playground
Moving'node/prefer-global/process': 'off'into the broaderplaygrounds/**override is correct—your new Electron IPC code relies on the globalprocessobject and this prevents lint errors in all playground variants.Optional refactor: Consolidate overrides
Theplaygrounds/**pattern appears in multiple override blocks (lines 33, 41, and 57). Consider merging these into a single block to reduce duplication and improve maintainability.playgrounds/electron/.gitignore (1)
1-6: Refine the log file ignore pattern
The pattern*.log*may unintentionally ignore files likelogic.js. It’s safer to target only log files.node_modules dist out .DS_Store .eslintcache -*.log* +*.logpackages/client/src/adapters/electron-ipc/consts.ts (1)
1-1: Consider adding a TSDoc comment for the constant
Documenting the purpose ofDEFAULT_ORPC_HANDLER_CHANNELwill help future maintainers understand its role in the IPC adapter.+/** + * Default channel name used for Electron IPC calls in oRPC client/server adapters. + */ export const DEFAULT_ORPC_HANDLER_CHANNEL = 'orpc:default'apps/content/docs/playgrounds.md (1)
23-23: Clarify missing StackBlitz link for Electron Playground
The StackBlitz column is empty; using—orN/Amakes it clear that this playground isn’t available on StackBlitz.-| Electron Playground | | [View Source](https://github.com/unnoq/orpc/tree/main/playgrounds/electron) | +| Electron Playground | — | [View Source](https://github.com/unnoq/orpc/tree/main/playgrounds/electron) |packages/server/src/adapters/electron-ipc/index.ts (1)
1-3: Address test coverage for re-export module
Static analysis flags missing coverage on these lines. Since this file only re-exports logic, consider adding a simple test that imports and asserts the exports (or updating coverage rules to exclude it). Let me know if you’d like help with a test snippet.🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 2-3: packages/server/src/adapters/electron-ipc/index.ts#L2-L3
Added lines #L2 - L3 were not covered by testsplaygrounds/electron/src/renderer/src/App.tsx (1)
4-13: Review component structure for accessibility and semantics.
Consider wrapping the header and sections in semantic HTML elements (e.g.,<header>,<main>,<section>) or adding ARIA attributes for better accessibility, especially as the playground UI expands.Optionally, you could update:
- <div> + <main> <h1>ORPC Playground</h1> <hr /> <CreatePlanetMutationForm /> <hr /> <ListPlanetsQuery /> - </div> + </main>playgrounds/electron/src/renderer/src/main.tsx (2)
6-6: Consider customizing QueryClient defaults
You may want to configure default options (e.g.,staleTime,cacheTime) onnew QueryClient({ defaultOptions: { queries: { ... } } })to better suit your playground’s data fetching needs.
8-14: Handle potential null root element
The non-null assertion (!) bypasses runtime checks. To improve robustness, explicitly guard against a missing#rootelement:-createRoot(document.getElementById('root')!).render( +const container = document.getElementById('root'); +if (!container) throw new Error('Root container not found'); +createRoot(container).render(playgrounds/electron/electron.vite.config.ts (1)
13-17: Clarify alias resolution path
For better clarity and portability, consider anchoring the alias to the config file’s directory:- '@renderer': resolve('src/renderer/src'), + '@renderer': resolve(__dirname, 'src/renderer/src'),This ensures the path remains correct regardless of the working directory.
playgrounds/electron/src/main/schemas/auth.ts (1)
8-10: Enhance token validation
Thetokenfield is a plain string. Optionally, you could enforce a JWT format or length check:token: z.string().regex(/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/, 'Invalid JWT')playgrounds/electron/tsconfig.web.json (1)
19-24: Optimize include globs
You can simplify yourincludepatterns by combining extensions:- "src/renderer/src/**/*", - "src/renderer/src/**/*.tsx", + "src/renderer/src/**/*.{ts,tsx}",This reduces redundancy.
playgrounds/electron/src/preload/index.ts (3)
5-6: Consider enhancing the custom API object with actual functionality.The
apiobject is currently empty but is exposed to the renderer process. If there are no custom APIs needed at this point, consider adding a comment explaining its purpose or future use, or consider removing it until needed.
11-19: Enhance error handling with specific actions.The error handling in the try-catch block currently logs the error but doesn't implement any recovery mechanism or specific actions based on the error type. Consider adding more robust error handling, especially for critical preload functionality.
try { contextBridge.exposeInMainWorld('electron', electronAPI) contextBridge.exposeInMainWorld('api', api) } catch (error) { console.error(error) + // Consider additional error handling or recovery actions + // For example: window.alert('Failed to initialize Electron API') }
20-25: Replace TypeScript ignore comments with proper type definitions.Using
@ts-expect-erroris a temporary solution. Consider adding proper type definitions in a declaration file instead.else { - // @ts-expect-error (define in dts) window.electron = electronAPI - // @ts-expect-error (define in dts) window.api = api }You could create a declaration file (e.g.,
electron-env.d.ts) with:interface Window { electron: typeof import('@electron-toolkit/preload').electronAPI; api: {}; // Define the type of your custom API }packages/server/src/adapters/electron-ipc/expose.test.ts (2)
18-33: Test description could be more specific.The current test name 'exposeORPCHandlerChannel' just repeats the function name without describing the behavior being tested. Consider renaming it to describe the expected behavior.
-it('exposeORPCHandlerChannel', () => { +it('should expose ORPC handler channel with send and receive methods', () => {Additionally, consider adding a test case for when context isolation is disabled, as this function might behave differently in that scenario.
29-32: Consider testing error handling scenarios.The test verifies the happy path but doesn't test how the function handles errors. Consider adding test cases for error scenarios, such as:
- What happens if contextBridge throws an error?
- What happens if ipcRenderer.on throws an error?
This would ensure the function handles error cases gracefully.
playgrounds/electron/src/main/orpc.ts (3)
5-6: Add documentation to clarify the purpose ofpub.Consider adding JSDoc comments to explain the purpose of the
pubexport and what functionality thedbProviderMiddlewareadds to it.+/** + * Public oRPC server object with database provider middleware. + * This can be used for endpoints that don't require authentication. + */ export const pub = os .use(dbProviderMiddleware)
8-9: Add documentation to clarify the purpose ofauthed.Consider adding JSDoc comments to explain the purpose of the
authedexport and emphasize that it builds on top ofpubby adding authentication requirements.+/** + * Authenticated oRPC server object. Extends the public server with authentication + * requirements. Use this for endpoints that require a logged-in user. + */ export const authed = pub .use(requiredAuthMiddleware)
1-9: Consider adding explicit type annotations.While TypeScript can infer the types, explicit type annotations would make the API contract clearer for consumers of these exports.
import { os } from '@orpc/server' import { dbProviderMiddleware } from './middlewares/db' import { requiredAuthMiddleware } from './middlewares/auth' -export const pub = os +export const pub = os as ReturnType<typeof os.use<typeof dbProviderMiddleware>> .use(dbProviderMiddleware) -export const authed = pub +export const authed = pub as ReturnType<typeof pub.use<typeof requiredAuthMiddleware>> .use(requiredAuthMiddleware)This would help developers understand exactly what they're working with when using these exports.
playgrounds/electron/src/main/middlewares/auth.ts (2)
18-21: Enhance type safety for context.The middleware adds a user to the context but doesn't explicitly type what it returns. Consider enhancing the type safety:
return next({ - context: { user: session.user }, + context: { + session, + user: session.user + }, })This way, downstream middlewares can access both the session and user directly, and the types are more complete.
4-6: Be more explicit about context types.The type definition for the context is minimal. Consider providing more comprehensive type information:
export const requiredAuthMiddleware = os - .$context<{ session?: { user?: User } }>() + .$context<{ + session?: { + user?: User; + // Add other session properties that might be relevant + }; + }>()Also consider defining the expected return context type to make the contract clearer.
playgrounds/electron/src/main/router/index.ts (1)
12-17: Consider adding JSDoc comments for better documentationWhile the naming is clear, adding JSDoc comments to describe the purpose and parameters of each procedure would improve developer experience, especially for consumers of this API.
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
7-7: Add configuration options to RPCLink constructorThe RPCLink is initialized with zero arguments, but may need configuration for more complex scenarios (like custom channel names, timeouts, etc.). Consider documenting what options are available or configurable.
-const link = new RPCLink() +// Initialize RPCLink with default configuration +// Consider adding options for custom IPC channel names, timeouts, etc. if needed +const link = new RPCLink({ + // Example: channelName: 'custom-ipc-channel', + // Example: timeout: 30000, +})playgrounds/electron/src/renderer/src/components/orpc-query.tsx (3)
4-11: Implement error handling with more details than just "Something went wrong"The infinite query setup is well-structured with good pagination parameters, but the error handling could be improved.
Consider enhancing the error handling to provide more context to users:
const { data, refetch, fetchNextPage, hasNextPage, status, error } = useSuspenseInfiniteQuery( orpc.planet.list.infiniteOptions({ input: cursor => ({ cursor, limit: 10 }), getNextPageParam: lastPage => lastPage.length === 10 ? lastPage.at(-1)?.id : null, initialPageParam: 0, }), ) if (status === 'error') { return ( <p> - Something went wrong. + Error loading planets: {error instanceof Error ? error.message : 'Unknown error'} </p> ) }
13-19: Consider adding a loading state indicatorThe component currently doesn't show a loading state when fetching additional pages.
You could add a loading indicator when fetching the next page:
const { data, refetch, fetchNextPage, hasNextPage, status, isFetchingNextPage } = useSuspenseInfiniteQuery( // ... existing options ) // ... existing code <button type="button" onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} > - Load more + {isFetchingNextPage ? 'Loading...' : 'Load more'} </button>
47-63: Add accessibility improvements to the table footerThe current implementation could benefit from some accessibility improvements.
<tfoot> <tr> <td colSpan={4}> <button type="button" onClick={() => fetchNextPage()} disabled={!hasNextPage} + aria-label="Load more planets" > Load more </button> <button type="button" onClick={() => refetch()} + aria-label="Refresh planet list" > Refresh </button> </td> </tr> </tfoot>packages/server/src/adapters/electron-ipc/expose.ts (1)
15-18: Consider adding error handling for IPC operationsThe IPC operations don't have any error handling, which could make debugging issues difficult.
contextBridge.exposeInMainWorld(channel, { - send: message => ipcRenderer.send(channel, message), + send: message => { + try { + ipcRenderer.send(channel, message); + } catch (error) { + console.error(`Error sending message on channel ${channel}:`, error); + throw error; + } + }, receive: callback => ipcRenderer.on(channel, (_, message) => callback(message)), } satisfies experimental_ExposedORPCHandlerChannel)playgrounds/electron/src/main/middlewares/retry.ts (1)
26-32: Add logging for retry attemptsThe current implementation doesn't log retry attempts, making it difficult to debug issues.
catch (e) { if (times >= options.times) { + console.warn(`Retry middleware: maximum retries (${options.times}) reached, re-throwing error`, e) throw e } + console.info(`Retry middleware: attempt ${times + 1}/${options.times} failed, retrying...`, e) times++ }playgrounds/electron/src/renderer/src/components/orpc-mutation.tsx (1)
41-55: Enhance form accessibility and validationThe form could benefit from additional accessibility attributes and client-side validation.
<form + aria-label="Create Planet Form" onSubmit={(e) => { // ...existing code }} > - <label> + <label htmlFor="planet-name"> Name - <input type="text" name="name" required /> + <input id="planet-name" type="text" name="name" required minLength="3" maxLength="50" /> </label> - <label> + <label htmlFor="planet-description"> Description - <textarea name="description" /> + <textarea id="planet-description" name="description" maxLength="500" /> </label> - <label> + <label htmlFor="planet-image"> Image - <input type="file" name="image" accept="image/*" /> + <input id="planet-image" type="file" name="image" accept="image/*" aria-describedby="image-help" /> + <span id="image-help" className="help-text">Optional. Maximum file size: 5MB</span> </label> <button type="submit">Submit</button> </form>playgrounds/electron/src/main/index.ts (2)
57-58: Replace console.log with structured logging.Using
console.logfor IPC test responses doesn't provide context about which component is logging or the severity level.Consider using a structured logging approach:
- ipcMain.on('ping', () => console.log('pong')) + ipcMain.on('ping', () => console.log('[IPC Test] Received ping, responding with pong'))
65-66: Missing braces for multi-line if statement.The if statement has no braces which can lead to bugs if more statements are added later.
- if (BrowserWindow.getAllWindows().length === 0) - createWindow() + if (BrowserWindow.getAllWindows().length === 0) { + createWindow() + }packages/client/src/adapters/electron-ipc/rpc-link.test.ts (5)
6-6: Replace delete operator with undefined assignment.Using the delete operator on globals can impact performance as noted by the static analysis tool.
- delete (globalThis as any)['orpc:default'] + (globalThis as any)['orpc:default'] = undefined🧰 Tools
🪛 Biome (1.9.4)
[error] 6-6: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
11-13: Fix typo in test description and improve error assertion.The test description has a grammatical error, and the error assertion doesn't verify the specific error message.
- it('it throw if not find exposed channel', () => { - expect(() => new RPCLink()).toThrow() + it('should throw if exposed channel is not found', () => { + expect(() => new RPCLink()).toThrow(/exposed channel not found/i)
18-21: Fix indentation in the code.There's unusual indentation with a semicolon at the beginning of line 18.
- ; (globalThis as any)['orpc:default'] = { - send, - receive, - } + (globalThis as any)['orpc:default'] = { + send, + receive, + }
30-30: Use a more explicit approach for asynchronous test flow.Using
setTimeoutwith 0 delay is a less clear way to wait for the next event loop cycle.- await new Promise(resolve => setTimeout(resolve, 0)) + await Promise.resolve() // Wait for next event loop cycle
55-55: Duplicate timeout pattern that could be extracted.The same timeout pattern is used in both test cases and could be extracted to a helper function.
+ const flushPromises = () => Promise.resolve() // In the first test: - await new Promise(resolve => setTimeout(resolve, 0)) + await flushPromises() // In the second test: - await new Promise(resolve => setTimeout(resolve, 0)) + await flushPromises()packages/server/package.json (1)
63-66: Specify experimental status in package exports.The exports don't indicate the experimental status of the Electron IPC adapter, unlike how it's imported in the code with an
experimental_prefix.Consider renaming the export or adding a note in the documentation to clearly indicate the experimental status.
playgrounds/electron/src/renderer/src/playground-query.ts (1)
18-21: Empty error handling logic.The error handling checks for a defined error but doesn't do anything with it.
Either implement proper error handling or remove the empty block:
onError(error) { if (isDefinedError(error)) { const id = error.data.id - // ^ type-safe + console.error(`Error updating planet with ID ${id}:`, error.message) + // Consider showing a notification or updating UI state here } },packages/server/src/adapters/electron-ipc/rpc-handler.test.ts (3)
37-50: Improve type safety in request message creationCurrently, the request messages are being cast with
as anywhich bypasses TypeScript's type checking. This could mask potential type-related issues, especially when handling binary data.Consider using proper type declarations instead of
as anycasts where possible:-const ping_request_message = await encodeRequestMessage(19, MessageType.REQUEST, { +type RequestPayload = Parameters<typeof encodeRequestMessage>[2]; + +const ping_request_message = await encodeRequestMessage(19, MessageType.REQUEST, { url: new URL('orpc:/ping'), body: { json: 'input' }, headers: {}, method: 'POST', -}) as any +} as RequestPayload) -const file_request_message = new TextEncoder().encode(await encodeRequestMessage(19, MessageType.REQUEST, { +const file_request_message = new TextEncoder().encode(await encodeRequestMessage(19, MessageType.REQUEST, { url: new URL('orpc:/file'), body: { json: 'input' }, headers: {}, method: 'POST', -}) as string) as any +} as RequestPayload) as string)
33-33: Consider adding a type annotation for clarityThe variable
onMessageis initialized asanytype, which can lead to type safety issues later in the test.-let onMessage: any +let onMessage: (event: { sender: any }, message: any) => void
68-81: Add a timeout to the test to prevent potential hangingThis test relies on
setTimeoutfor asynchronous operations but doesn't have an explicit timeout. While it's unlikely to cause issues with the current implementation, it's a good practice to add timeouts to prevent tests from hanging indefinitely if there's an issue.-it('on success', async () => { +it('on success', async () => { onMessage({ sender }, ping_request_message) await new Promise(resolve => setTimeout(resolve, 20)) const [id, , payload] = (await decodeResponseMessage(sender.send.mock.calls[0]![1])) expect(id).toBeTypeOf('number') expect(payload).toEqual({ status: 200, headers: {}, body: { json: 'pong' }, }) -}) +}, 100)packages/client/src/adapters/electron-ipc/link-client.ts (2)
23-27: Improve error message for missing ORPC handler channelWhen the exposed ORPC handler channel is not found in the global context, a more detailed error message could help users with troubleshooting.
if (!exposed) { - throw new Error(`Cannot find exposed ORPC handler channel at globalThis['${channel}']`) + throw new Error(`Cannot find exposed ORPC handler channel at globalThis['${channel}']. Make sure you have called 'exposeORPCHandlerChannel()' in your preload script and your preload script is properly configured in your Electron app.`) }
38-41: Simplify thecallmethod implementationThe current implementation creates a new object with a body accessor function that immediately resolves the body. This seems unnecessary as the body is already resolved.
async call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse> { const response = await this.peer.request(request) - return { ...response, body: () => Promise.resolve(response.body) } + return { ...response, body: () => Promise.resolve(response.body) } }Actually, it might be more efficient to just return:
async call(request: StandardRequest, _options: ClientOptions<T>, _path: readonly string[], _input: unknown): Promise<StandardLazyResponse> { const response = await this.peer.request(request) - return { ...response, body: () => Promise.resolve(response.body) } + return response }This depends on whether
responsealready implements theStandardLazyResponseinterface correctly. If it does, there's no need to create a new object.playgrounds/electron/package.json (1)
22-25: Use specific versions for internal dependenciesThe ORPC libraries are specified with "next" tag instead of specific versions. This could lead to unexpected breaking changes when new versions are released.
Consider pinning internal dependencies to specific versions or version ranges to ensure predictable builds and prevent unexpected breaking changes.
- "@orpc/client": "next", - "@orpc/react-query": "next", - "@orpc/server": "next", - "@orpc/zod": "next", + "@orpc/client": "^1.0.0", + "@orpc/react-query": "^1.0.0", + "@orpc/server": "^1.0.0", + "@orpc/zod": "^1.0.0",playgrounds/electron/src/main/schemas/user.ts (1)
4-5: Type exports defined before their implementationsThe type exports on lines 4-5 reference schemas that are defined later in the file. While this works in TypeScript, it's generally better practice to define types after their implementations for readability.
Consider moving the type exports after their schema implementations:
import { oz } from '@orpc/zod' import { z } from 'zod' - export type NewUser = z.infer<typeof NewUserSchema> - export type User = z.infer<typeof UserSchema> - export const NewUserSchema = oz.openapi( /* ... */ ) export const UserSchema = oz.openapi( /* ... */ ) + export type NewUser = z.infer<typeof NewUserSchema> + export type User = z.infer<typeof UserSchema>packages/client/src/adapters/electron-ipc/rpc-link.ts (1)
7-8: Improve interface readability with line breaksThe interface declaration extends across a long line which reduces readability. Breaking this into multiple lines would improve code clarity.
- export interface experimental_RPCLinkOptions<T extends ClientContext> - extends Omit<StandardRPCLinkOptions<T>, 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength'>, LinkElectronIPCClientOptions {} + export interface experimental_RPCLinkOptions<T extends ClientContext> + extends Omit< + StandardRPCLinkOptions<T>, + 'url' | 'headers' | 'method' | 'fallbackMethod' | 'maxUrlLength' + >, + LinkElectronIPCClientOptions {}playgrounds/electron/electron-builder.yml (1)
21-28: Consider enabling notarization for macOS production buildsNotarization is currently disabled (
notarize: false), which is fine for development but may cause security warnings when distributing the app to macOS users in production. For the playground this is acceptable, but document this requirement if this configuration will be used as a template for production apps.playgrounds/electron/src/main/middlewares/db.ts (1)
73-75: Add bounds checking to list methodThe
listmethod doesn't handle cases wherecursor + limitexceeds the array length, which could potentially cause issues.list: async (limit: number, cursor: number) => { - return planets.slice(cursor, cursor + limit) + return planets.slice(cursor, Math.min(cursor + limit, planets.length)) },playgrounds/electron/src/main/schemas/planet.ts (1)
22-28: Consider adding validation for imageUrl patternThe
imageUrlfield is validated as a URL, but you might want to consider adding a pattern validation to ensure it matches the format used in your create and update methods (e.g.,https://example.com/cdn/{filename}).- imageUrl: z.string().url().optional(), + imageUrl: z.string().url().regex(/^https:\/\/example\.com\/cdn\/.*/).optional(),packages/server/src/adapters/electron-ipc/handler.ts (2)
38-47: Lifecycle-clean-up looks good – but watch for other WebContents exit signalsHooking the
destroyedevent is great, butWebContentscan also disappear viacrashed,did-fail-load, ordid-navigate(which produces a fresh WebContents instance).
If a crash/navigation occurs without emittingdestroyed, theServerPeermay linger in#peers, preventing GC of large message buffers.It’s worth listening for
crashedanddid-navigate(checkingevent.isDestroyed()on callback) and performing the samepeer.close()/ map cleanup.
40-41: Broaden binary payload handling
raw instanceof Blobonly covers browser-sideBlob. In Node/Electron, large binary bodies are more commonlyBufferorArrayBuffer.
To avoid silently sending an unsupported object over IPC, convert additional types, e.g.:-event.sender.send(this.#channel, raw instanceof Blob ? await raw.arrayBuffer() : raw) +const payload = + raw instanceof Blob ? await raw.arrayBuffer() + : Buffer.isBuffer(raw) ? raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength) + : raw +event.sender.send(this.#channel, payload)playgrounds/electron/src/main/router/planet.ts (4)
16-20: Minor:default()+min()interplay
limitandcursordeclare bothmin()anddefault().
Zod appliesdefault()first, then validation, so the defaults (10, 0) themselves pass themin()constraint. That’s fine, but if your intent was “optional but validated only when provided”, you can achieve that more clearly with.optional().default(value)(avoids the double-validation).
40-44: Retry middleware – consider back-offThree immediate retries in a tight
while(true)loop can hammer the database if it is already under load. A simple exponential back-off (e.g.,await delay(2 ** times * 50)) inside the catch branch would mitigate burst traffic during transient failures.
70-75:errors.NOT_FOUNDschema: simplify with.pick()You can avoid repeating the
idtype by re-using the existing schema:-data: z.object({ id: UpdatePlanetSchema.shape.id }), +data: UpdatePlanetSchema.pick({ id: true }),This reduces maintenance friction if the
idconstraints change later.
81-95: Remove commented-out legacy code before mergingThe alternative
ORPCErrorthrow (lines 90-94) is valuable history but clutters the production code path. Move it to git history or project docs to keep the source clean.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (51)
apps/content/.vitepress/config.ts(2 hunks)apps/content/docs/adapters/ipc.md(1 hunks)apps/content/docs/integrations/electron-ipc.md(1 hunks)apps/content/docs/playgrounds.md(2 hunks)eslint.config.js(1 hunks)package.json(1 hunks)packages/client/package.json(3 hunks)packages/client/src/adapters/electron-ipc/consts.ts(1 hunks)packages/client/src/adapters/electron-ipc/index.ts(1 hunks)packages/client/src/adapters/electron-ipc/link-client.ts(1 hunks)packages/client/src/adapters/electron-ipc/rpc-link.test.ts(1 hunks)packages/client/src/adapters/electron-ipc/rpc-link.ts(1 hunks)packages/client/src/adapters/electron-ipc/types.ts(1 hunks)packages/server/package.json(4 hunks)packages/server/src/adapters/electron-ipc/expose.test.ts(1 hunks)packages/server/src/adapters/electron-ipc/expose.ts(1 hunks)packages/server/src/adapters/electron-ipc/handler.ts(1 hunks)packages/server/src/adapters/electron-ipc/index.ts(1 hunks)packages/server/src/adapters/electron-ipc/rpc-handler.test.ts(1 hunks)packages/server/src/adapters/electron-ipc/rpc-handler.ts(1 hunks)playgrounds/electron/.gitignore(1 hunks)playgrounds/electron/.vscode/settings.json(1 hunks)playgrounds/electron/README.md(1 hunks)playgrounds/electron/electron-builder.yml(1 hunks)playgrounds/electron/electron.vite.config.ts(1 hunks)playgrounds/electron/package.json(1 hunks)playgrounds/electron/src/main/index.ts(1 hunks)playgrounds/electron/src/main/middlewares/auth.ts(1 hunks)playgrounds/electron/src/main/middlewares/db.ts(1 hunks)playgrounds/electron/src/main/middlewares/retry.ts(1 hunks)playgrounds/electron/src/main/orpc.ts(1 hunks)playgrounds/electron/src/main/router/auth.ts(1 hunks)playgrounds/electron/src/main/router/index.ts(1 hunks)playgrounds/electron/src/main/router/planet.ts(1 hunks)playgrounds/electron/src/main/router/sse.ts(1 hunks)playgrounds/electron/src/main/schemas/auth.ts(1 hunks)playgrounds/electron/src/main/schemas/planet.ts(1 hunks)playgrounds/electron/src/main/schemas/user.ts(1 hunks)playgrounds/electron/src/preload/index.d.ts(1 hunks)playgrounds/electron/src/preload/index.ts(1 hunks)playgrounds/electron/src/renderer/index.html(1 hunks)playgrounds/electron/src/renderer/src/App.tsx(1 hunks)playgrounds/electron/src/renderer/src/components/orpc-mutation.tsx(1 hunks)playgrounds/electron/src/renderer/src/components/orpc-query.tsx(1 hunks)playgrounds/electron/src/renderer/src/lib/orpc.ts(1 hunks)playgrounds/electron/src/renderer/src/main.tsx(1 hunks)playgrounds/electron/src/renderer/src/playground-client.ts(1 hunks)playgrounds/electron/src/renderer/src/playground-query.ts(1 hunks)playgrounds/electron/tsconfig.json(1 hunks)playgrounds/electron/tsconfig.node.json(1 hunks)playgrounds/electron/tsconfig.web.json(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (15)
packages/server/src/adapters/electron-ipc/rpc-handler.ts (3)
packages/server/src/context.ts (1)
Context(1-1)packages/server/src/adapters/standard/rpc-handler.ts (2)
StandardRPCHandlerOptions(10-11)StandardRPCHandler(13-22)packages/server/src/router.ts (1)
Router(12-17)
playgrounds/electron/src/renderer/src/components/orpc-query.tsx (1)
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
orpc(11-11)
playgrounds/electron/src/renderer/src/main.tsx (1)
playgrounds/solid-start/src/app.tsx (1)
App(8-22)
playgrounds/electron/src/renderer/src/playground-query.ts (1)
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
orpc(11-11)
playgrounds/electron/src/renderer/src/playground-client.ts (1)
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
orpc(11-11)
playgrounds/electron/src/renderer/src/components/orpc-mutation.tsx (1)
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
orpc(11-11)
playgrounds/electron/src/renderer/src/lib/orpc.ts (4)
packages/client/src/adapters/fetch/rpc-link.ts (1)
RPCLink(16-22)packages/server/src/router-client.ts (1)
RouterClient(14-19)playgrounds/electron/src/main/router/index.ts (1)
router(5-20)packages/client/src/client.ts (1)
createORPCClient(16-42)
playgrounds/electron/src/main/middlewares/db.ts (4)
playgrounds/electron/src/main/schemas/planet.ts (3)
Planet(7-7)NewPlanet(5-5)UpdatePlanet(6-6)playgrounds/electron/src/main/schemas/user.ts (1)
User(5-5)playgrounds/electron/src/main/router/planet.ts (1)
updatePlanet(63-98)packages/server/src/builder.ts (1)
os(336-352)
playgrounds/electron/src/main/middlewares/retry.ts (1)
packages/server/src/builder.ts (1)
os(336-352)
packages/server/src/adapters/electron-ipc/expose.ts (2)
packages/client/src/adapters/electron-ipc/consts.ts (1)
DEFAULT_ORPC_HANDLER_CHANNEL(1-1)packages/client/src/adapters/electron-ipc/types.ts (1)
experimental_ExposedORPCHandlerChannel(1-4)
playgrounds/electron/src/main/schemas/user.ts (1)
packages/zod/src/index.ts (1)
oz(16-22)
playgrounds/electron/src/main/router/auth.ts (3)
playgrounds/electron/src/main/orpc.ts (2)
pub(5-6)authed(8-9)playgrounds/electron/src/main/schemas/user.ts (2)
NewUserSchema(7-22)UserSchema(24-39)playgrounds/electron/src/main/schemas/auth.ts (2)
CredentialSchema(3-6)TokenSchema(8-10)
playgrounds/electron/src/main/router/planet.ts (3)
playgrounds/electron/src/main/orpc.ts (2)
pub(5-6)authed(8-9)playgrounds/electron/src/main/middlewares/retry.ts (1)
retry(3-35)playgrounds/electron/src/main/schemas/planet.ts (3)
PlanetSchema(22-28)NewPlanetSchema(9-13)UpdatePlanetSchema(15-20)
playgrounds/electron/src/main/middlewares/auth.ts (2)
packages/server/src/builder.ts (1)
os(336-352)playgrounds/electron/src/main/schemas/user.ts (1)
User(5-5)
playgrounds/electron/src/main/schemas/planet.ts (2)
packages/zod/src/index.ts (1)
oz(16-22)playgrounds/electron/src/main/schemas/user.ts (1)
UserSchema(24-39)
🪛 markdownlint-cli2 (0.17.2)
playgrounds/electron/README.md
17-17: Images should have alternate text (alt text)
null
(MD045, no-alt-text)
🪛 GitHub Check: codecov/patch
packages/server/src/adapters/electron-ipc/index.ts
[warning] 2-3: packages/server/src/adapters/electron-ipc/index.ts#L2-L3
Added lines #L2 - L3 were not covered by tests
🪛 Biome (1.9.4)
packages/client/src/adapters/electron-ipc/rpc-link.test.ts
[error] 6-6: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
packages/server/src/adapters/electron-ipc/expose.test.ts
[error] 15-15: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
packages/server/src/adapters/electron-ipc/rpc-handler.test.ts
[error] 61-66: Disallow duplicate setup and teardown hooks.
Disallow beforeEach duplicacy inside the describe function.
(lint/suspicious/noDuplicateTestHooks)
🔇 Additional comments (40)
playgrounds/electron/.vscode/settings.json (1)
1-3: Enable VSCode format-on-save
This setting correctly enforces code formatting on every save, which helps maintain consistency in the playground.apps/content/.vitepress/config.ts (2)
90-90: Add IPC adapter link to the sidebar
This correctly integrates the new IPC adapter documentation under the “Adapters” section, making it discoverable.
109-109: Add Electron IPC integration link to the sidebar
Including this under “Integrations” ensures users can easily find the Electron IPC guide.playgrounds/electron/tsconfig.json (1)
1-4: Root TypeScript Project References
Thetsconfig.jsoncorrectly references bothtsconfig.node.jsonandtsconfig.web.json. Ensure each referenced config has"composite": trueto support project references.packages/client/src/adapters/electron-ipc/index.ts (1)
1-4: Centralize Electron IPC client exports
Re-exporting fromconsts,link-client,rpc-link, andtypesprovides a clear, single entry point for consumers.package.json (1)
51-56: Optimize pnpm build withonlyBuiltDependencies
Definingelectronandesbuildhere streamlines native builds for the Electron playground and adapters. This is a solid enhancement for build performance.playgrounds/electron/src/renderer/src/App.tsx (2)
1-2: Approve import usage in the renderer entry point.
ImportsCreatePlanetMutationFormandListPlanetsQuerycorrectly reflect the new oRPC components.
16-17: Approve default export.
The default export of theAppcomponent follows convention for React entry points.playgrounds/electron/src/preload/index.d.ts (1)
1-8: Approve global window augmentation.
Thedeclare globalaugmentation withelectron: ElectronAPIandapi: unknownaligns with the preload script’s exposure, and the use ofimport typeensures this remains a type-only import.playgrounds/electron/src/renderer/index.html (1)
1-17: Approve minimal HTML and CSP configuration.
The provided HTML structure and strict Content Security Policy correctly initialize the renderer and mitigate script injection risks. Ensure this policy doesn’t block any Vite HMR scripts in development.You may want to verify that hot module replacement (HMR) works under this CSP during local development.
playgrounds/electron/tsconfig.node.json (1)
1-13: Approve Node-targeted TypeScript config.
Extending the Electron Toolkit’s base config and adjustingmoduleResolutiontobundleris appropriate for the Electron main/preload context. Disabling unused checks here helps reduce noise during development.apps/content/docs/adapters/ipc.md (3)
1-4: Frontmatter is well-formed
The YAML frontmatter correctly definestitleanddescriptionfor this page.
10-13: Table formatting and links look good
The adapter table is clear and the links point to the correct Electron docs and integration guide.
14-16: Verify docs link resolution
Ensure that the relative link[docs](/docs/integrations/electron-ipc)correctly resolves in the VitePress site.playgrounds/electron/src/renderer/src/main.tsx (1)
1-4: Imports and setup are correct
The import ofStrictMode,createRoot, and React Query components is appropriate for a React 18+ application.playgrounds/electron/electron.vite.config.ts (1)
1-4: Imports are correct
Usingnode:pathandelectron-viteimports aligns with the recommended pattern for Electron Vite configs.playgrounds/electron/tsconfig.web.json (2)
3-6: Base config extension is correct
Extending@electron-toolkit/tsconfig/tsconfig.web.jsonand settingjsx/moduleResolutionis appropriate for a React renderer.
15-16: Review disabling unused checks
You’ve setnoUnusedLocalsandnoUnusedParameterstofalse, which may allow dead code to accumulate. Verify that this is intentional.playgrounds/electron/src/preload/index.ts (1)
27-27: Consider conditionally exposing ORPC handler channel.The
exposeORPCHandlerChannel()function is called unconditionally, outside of the context isolation check. Consider whether this should also be conditional based on context isolation, or add a comment explaining why it's called unconditionally.playgrounds/electron/src/main/router/index.ts (1)
5-20: Well-organized router structureThe router implementation provides a clean, hierarchical organization of RPC procedures grouped by domain (auth, planet) with clear naming conventions. This structure makes the API surface easy to understand and maintain.
playgrounds/electron/src/main/router/sse.ts (1)
14-22: Clean implementation of SSE using async generatorThis is a good example of leveraging async generators to implement server-sent events. The yield pattern with setTimeout creates a clean streaming implementation.
playgrounds/electron/src/renderer/src/lib/orpc.ts (1)
9-11: Well-typed client implementation with React Query integrationThe implementation uses TypeScript's type system effectively to create a strongly-typed client that matches the main process router structure. The integration with React Query is clean and follows best practices.
playgrounds/electron/src/renderer/src/components/orpc-query.tsx (1)
1-2: Good import choice for querying with oRPC and React QueryUsing
useSuspenseInfiniteQueryis a good choice for paginated data fetching, and the minimal imports keep the component focused.packages/server/src/adapters/electron-ipc/expose.ts (2)
1-3: Good import organization for the IPC adapterThe imports are well-structured, with type imports separated from value imports.
5-11: Well-documented function with clear purposeThe JSDoc documentation clearly explains the function's purpose and includes a link to further documentation.
playgrounds/electron/src/main/middlewares/retry.ts (2)
1-2: Good import for server middleware contextThe import is clean and focused, only bringing in what's needed.
3-16: Good implementation of middleware with context type safetyThe middleware initialization with typed context is well done. The early return for non-retry contexts prevents unnecessary processing.
playgrounds/electron/src/renderer/src/components/orpc-mutation.tsx (1)
1-2: Good import choice for mutations with oRPC and React QueryUsing
useMutationanduseQueryClienttogether is the right approach for cache invalidation after mutations.playgrounds/electron/src/main/index.ts (1)
4-4: Use a stable import rather than experimental APIs.The code imports an experimental API and renames it to hide the experimental nature:
import { experimental_RPCHandler as RPCHandler } from '@orpc/server/electron-ipc'Experimental APIs are subject to breaking changes in future releases. Consider one of these approaches:
- Keep the experimental prefix to make it clear to other developers that this API may change
- Check if a stable version of this API is available
- Document the risk of using experimental APIs in comments
apps/content/docs/integrations/electron-ipc.md (1)
1-46: Comprehensive and well-structured documentation for Electron IPC integrationThe documentation clearly outlines the three-step process for integrating oRPC with Electron's IPC mechanism across main, preload, and renderer processes. The code examples are concise and demonstrate the proper usage of the experimental APIs.
The reference to additional information in the IPC Adapter guide and the note about client-side examples are helpful for users seeking more detailed context.
packages/server/src/adapters/electron-ipc/rpc-handler.ts (1)
1-21: Well-structured and cleanly implemented adapter classThe
experimental_RPCHandlerclass provides a clear integration between the standard RPC handler and Electron IPC handler. The class extends the appropriate base class and follows the composition pattern by instantiating theStandardRPCHandlerwith the provided router and options.The code structure is clean, and the type definitions are comprehensive with proper JSDoc comments for documentation.
playgrounds/electron/package.json (1)
26-38:Details
❓ Verification inconclusive
Verify dependency compatibility
The dependencies include very recent versions (React 19, Node 22, TypeScript 5.8) which might have compatibility issues or be in beta/unstable state.
🌐 Web query:
Is React 19 stable and production-ready? What are the compatibility considerations?💡 Result:
Is React 19 Stable and Production-Ready?
React 19 is officially stable and considered production-ready as of its December 2024 release[2][5][1]. The React core team has thoroughly tested the release, and it introduces significant improvements in performance, developer experience, and scalability, building upon the solid foundation of React 18[2][1][5]. Notably, features like the React Compiler, Actions API, improved Suspense, and React Server Components are now stable and ready for use in modern applications[1][2][4][5].
“React 19 is now stable! ... React v19 is now available on npm!” [2]
Compatibility Considerations
While React 19 itself is stable, upgrading existing projects—especially those that depend on a wide ecosystem of third-party libraries—requires careful attention. Here are the key compatibility points to consider:
Backward Compatibility
- React 19 maintains backward compatibility with most existing React 18 code, and the migration process is designed to be smooth, with detailed upgrade guides provided by the React team[1][2][5].
Third-Party Library Support
- Many popular libraries have not yet released versions fully compatible with React 19, leading to potential warnings or errors during installation or runtime[6][9].
- The stricter peer dependency checking introduced in npm v7+ now throws installation errors for mismatches that might have previously gone unnoticed. This exposes incompatibilities more clearly but can also make upgrades more disruptive[6][9].
- Developers have reported that, nearly a year after release, “many packages don’t support it without —force or legacy deps,” so you may encounter issues if your project relies on a broad array of community libraries[6].
Migration Procedures and Best Practices
- Check Package Compatibility: Before upgrading, audit your dependencies to ensure that they explicitly support React 19[9][6][7].
- Test Thoroughly: Focus on areas where breaking changes could impact your code—such as stricter ref forwarding, lifecycle method updates, and the new behaviors in Suspense and Server Components[9][5].
- Handle Peer Dependencies Carefully: If you hit peer dependency errors, options include using
--forceor--legacy-peer-depswith npm, or leveraging theoverridesfield inpackage.json—but these are workarounds and may lead to runtime problems if underlying incompatibility exists[6].- Gradual Upgrades: For larger codebases or libraries, consider supporting both React 18 and 19 through conditional exports and careful TypeScript typing, as demonstrated by the MUI X team[7].
Notable Breaking Changes
- Stricter ref handling: Updates to
useRef()andRefObjecttyping may require refactoring, especially in TypeScript projects[7][9].- Lifecycle cleanups: React 19 cleans up effects more aggressively, which may reveal previously unnoticed bugs in component unmount logic[9].
- Error boundaries and reporting: Error handling APIs are more robust, with new hooks and logging behaviors introduced[2][5].
Framework and Tooling Support
- Frameworks like Next.js and TanStack Start have been actively updating to integrate the latest React features, but project defaults and documentation may still lag, with some tools defaulting to React 18[8][6].
- Review community migration guides and changelogs for your primary frameworks before upgrading core dependencies[7][9].
Summary Table: React 19 Stability and Compatibility
Aspect Status/Consideration Core React 19 Stable and production-ready[1][2][5] Backward Compatibility Strong, smooth migration path from React 18[1][2][5] Third-party Library Support Mixed—many libraries still updating, check before upgrading[6][9] npm Peer Dependencies Enforced strictly, can block incompatible installs[6][9] Ref & Lifecycle Changes Breaking changes may require small refactors[7][9] Server Component Support Now considered stable in React 19[4][5] Framework Support (Next.js) Mostly compatible, but verify before large upgrades[8][7] Conclusion
React 19 is stable and production-ready, offering notable performance gains and new features[1][2][5]. However, real-world adoption depends on the compatibility of your wider stack, especially third-party libraries and tooling. Before upgrading, audit dependencies, test thoroughly, and consult migration documentation to ensure a smooth transition[6][9][7]. If you rely heavily on community packages, you may find it prudent to wait for more ecosystem updates—or prepare to address compatibility issues as you encounter them.
Citations:
- 1: https://weqtechnologies.com/react-19-features-updates-2025-whats-new-why-it-matters/
- 2: https://react.dev/blog/2024/12/05/react-19
- 3: https://www.youtube.com/watch?v=dCLhUialKPQ
- 4: https://prevaj.com/whats-new-in-react-19-features-changes-and-what-to-expect/
- 5: https://pagepro.co/blog/react-tldr/react-19-released/
- 6: https://www.wisp.blog/blog/react-191-is-out-heres-what-you-need-to-know
- 7: https://mui.com/blog/react-19-update/
- 8: https://blog.probirsarkar.com/10-most-hyped-react-libraries-and-frameworks-of-2025-055f35df203b
- 9: https://blog.openreplay.com/common-mistakes-upgrading-react-19-avoid/
- 10: https://www.codifynext.com/blog/react-19-comprehensive-overview-and-new-features
React 19 is stable, but audit your dependencies for compatibility
React 19 is officially stable and production-ready, with strong backward compatibility from React 18. However, many community libraries are still updating their peer dependencies, so it’s important to verify that your stack supports React 19 before shipping.
Please review the following in playgrounds/electron/package.json (lines 26–38):
- Confirm that each dependency declares React 19 support in its peerDependencies, especially:
@tanstack/react-query@^5.72.3@vitejs/plugin-react@^4.4.1andvite@^6.3.5- Any other React-related plugins or tooling
- Run
npm install(orpnpm install) and address any peer-dependency warnings or errors.- If you encounter conflicts, consider using the
overridesfield or--legacy-peer-deps, but only as a temporary workaround.- Test key areas (ref forwarding, Suspense, Server Components) to catch subtle breaking changes.
playgrounds/electron/electron-builder.yml (2)
42-43: Verify auto-update URL for production useThe auto-update URL is currently set to a placeholder (
https://example.com/auto-updates). Ensure this is intentional for the playground, or update it to the actual URL before deploying to production.
1-11: App configuration looks goodThe basic app configuration is well-structured with appropriate app ID, product name, and file inclusions/exclusions for the Electron build process.
packages/client/package.json (2)
43-47: Export configuration for Electron IPC adapter is properly structuredThe export entries for the new Electron IPC adapter are correctly added to the publishConfig section.
55-56: Source exports properly configuredThe source exports for the Electron IPC adapter are correctly specified.
playgrounds/electron/src/main/middlewares/db.ts (2)
14-29: Good use of deduplication middleware patternThe middleware implementation correctly follows the documented best practice for deduplication by using the nullish coalescing operator to avoid unnecessary creation of the fake DB.
67-91: Create method implementation looks goodThe create method correctly generates a new ID, handles optional image URLs, and adds the new planet to the in-memory database.
playgrounds/electron/src/main/schemas/planet.ts (2)
9-13: NewPlanetSchema is well-structuredThe schema properly defines required and optional fields with appropriate validations. Good use of the
oz.file()validator with type restriction to only accept image files.
15-20: UpdatePlanetSchema looks goodThe schema correctly extends the new planet schema with a required ID field.
|
@unnoq really appreciate your work on adding this! I was discussing this with my colleague @mutewinter and I'm taking a look at the PR. We're big fans of orpc and would love to be able to use this in Electron. I'm testing it locally and will provide feedback where I can. The instructions are straightforward and make sense. I also ran the playground locally and it works fine for me. Very straightforward. One thing so far: I'm seeing an issue because the Here is the exception that's thrown: import { contextBridge, ipcRenderer, ipcMain } from 'electron';
^^^^^^^^^^^^^
SyntaxError: The requested module 'electron' does not provide an export named 'contextBridge' |
|
Thanks @aortbals. By moving the API related to |
|
Checkout my new implementation with Message Port: https://github.com/unnoq/orpc/pull/528 |
|
Great, i'll take a look. FWIW, I did determine it was tree-shaking that allowed it to work in the playground with the import and it wasn't working due to our custom use of the |
Replaces: https://github.com/unnoq/orpc/pull/500 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced message port adapters for oRPC enabling type-safe RPC communication across Electron, browser extensions, and Node.js worker threads. - Added detailed documentation and integration guides for message port usage in multiple environments. - Launched new Electron and Browser Extension playgrounds with example apps demonstrating full-stack oRPC integration. - Provided React components and hooks for querying and mutating data using oRPC in both Electron and browser extension UIs. - Added authentication, retry, and database middlewares with typed API routes for user and planet management in playgrounds. - Implemented server-sent events (SSE) endpoints in playground environments. - **Bug Fixes** - Improved ESLint configuration coverage for playground directories. - **Documentation** - Expanded documentation with new sections and guides for message port adapters, Electron, browser extensions, and worker threads. - Updated playground documentation to include new environments and setup instructions. - **Tests** - Added extensive test suites for message port adapters, ensuring correct message handling, error processing, and integration with oRPC clients and servers. - **Chores** - Added configuration files and package setups for new playgrounds, including TypeScript, Vite, Electron Builder, and WXT configurations. - Added new package.json configurations for client, server, and playground packages supporting message-port adapters and playground builds. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary by CodeRabbit
New Features
Documentation
Tests
Chores